kubernetes-部署
部署kubernetes master
部署容器网络插件
部署worker节点
部署dashboard可视化插件
部署容器存储插件
以下操作均是在centos7.6进行
- 部署kubernetes master
# curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && curl -o /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
# 关闭selinux
# sed -i 's/enforcing/disabled/g' /etc/sysconfig/selinux
安装基础组件
# yum install -y kubelet kubeadm kubectl docker-ce vim iptables-services wget net-tools
# systemctl start docker && systemctl enable docker kubelet
导入基础镜像
# docker load -i k8s1.15.1.tar
注:以上操作需要在所有节点执行,本次部署需要有互联网支持
master节点进行初始化
忽略swap报错
# vim /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--fail-swap-on=false"
安装
# kubeadm init --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --ignore-preflight-errors=Swap --kubernetes-version=v1.15.1
注:10.244.0.0/16为pod网络 server网络默认为10.96.0.0/12
kubectl 客户端用户配置文件配置
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
记录安装后输出,供后面添加node节点使用
# kubeadm join 192.168.1.170:6443 --token gpy810.gaq18z5bnks9occf \
--discovery-token-ca-cert-hash sha256:747559b3a32db293cd063a77559c85d04469026145d99cf97fe4fac002717512
查看节点信息
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master.k8s.com NotReady master 38m v1.15.1
以上的get输出结果可以看到,master节点的状态是NotReady,在调试k8s集群时,最重要的手段就是用kubectl describe 命令查看节点(node)对象的详细信息、状态和事件(Event),执行以下命令进行排查
# kubectl describe node master
...
Conditions:
...
Ready False ... KubeletNotReady runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
通过kubectl describe 命令输出可以看到,NotReady的原因是还没有部署网络插件
另外,还可以通过kubectl检查这个节点上各个系统pod的状态,其中,kube-system是k8s预留的系统pod的工作空间。
# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-78fcdf6894-j9syh 0/1 Pending 0 1h
coredns-78fcdf6894-jm8df 0/1 Pending 0 1h
etcd-master 1/1 Running 0 2s
kube-apiserver-master 1/1 Running 0 1s
kube-controller-manager-master 0/1 Pending 0 1s
kube-proxy-xb7u7 1/1 NodeLost 0 1h
kube-scheduler-master 1/1 Running 0 1s
可以看到,coredns、kube-controller-manager等依赖于网络的pod都处于Pending状态,也就是调度失败,这是符合预期效果的,因为这个master节点的网络还没部署。
- 部署容器网络插件
# kubectl apply -f kube-flannel.yml
部署完成后,可以通过kubectl get 重新检查一遍pod状态。
# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-5c98db65d4-cp2zj 1/1 Running 0 11d
coredns-5c98db65d4-t6rqq 1/1 Running 0 11d
etcd-master.k8s.com 1/1 Running 0 11d
kube-apiserver-master.k8s.com 1/1 Running 0 11d
kube-controller-manager-master.k8s.com 1/1 Running 0 11d
kube-flannel-ds-amd64-gkck5 1/1 Running 1 11d
kube-proxy-gjswz 1/1 Running 1 11d
kube-proxy-s48w4 1/1 Running 0 11d
kube-scheduler-master.k8s.com 1/1 Running 0 11d
可以看到,所有的pod都启动成功了,而刚刚部署的flannel网络插件则在kube-system新建了一个名叫kube-flannel-ds-amd64-gkck5的pod,一般来说,这些pod就是容器网络插件在每个节点上的控制组件。
k8s支持容器网络插件,使用的是一个叫CNI的通用接口,它也是当前容器网络的标准,市面上所的所有容器网络开源项目都可以通过CNI接入k8s,比如刚部署的flannel还有calico、canal、romana等等,它们的部署方式也都是类似的“一键部署”。
至此k8s的master节点就部署完成了,如果只需要一个蛋节点的k8s,现在就可以使用了,不过在默认情况下,k8s的master节点是不能运行用户pod的,所以还需要额外做一个小操作。
使用taint/toleration调整master执行pod的策略。
它的原理非常简单,一旦某个节点被加上一个taint,也就是被打上了“污点”,那么所有pod就都不能在这个节点上运行,因为k8s是有洁癖的。
除非有个别的pod声明自己能“容忍”这个“污点”,也就是声明了toleration,它才可以在这个节点上运行。
其中,为节点打上"污点"(taint)的命令如下:
# kubectl taint nodes master.k8s.com foo=bar:NoSchedule
这时master.k8s.com这台master节点就会增加一个键值对格式的taint,其中值里面的NoSchedule,意味着这个taint只会在调度新pod的时候生效,而不会影响到已经发布到master节点上的pod,即便他们没有toleration。
声明toleration,只需要在pod的yaml文件中spec部分,加入tolerations字段即可,如下:
apiVersion: v1
kind: Pod
...
spec:
tolerations:
- key: "foo"
operator: "Equal"
value: "bar"
effect: "NoSchedule"
这个toleration的含义是,这个pod能“容忍”所有键值对为foo=bar的taint(operator:"Equal",“等于”操作)。
回到已经部署的集群个上,这时,如果通过kubectl describe检查一下master节点的taint字段,就会有些发现
kubectl describe node master
Name: master
Roles: master
Taints: node-role.kubernetes.io/master:NoSchedule
可以看到,master节点默认被加上了node-role.kubernetes.io/master:NoSchedule这样一个“污点”,其中"键"是node-role.kubernetes.io/master,而没有提供“值”。
此时,就需要像下面这样用“Exists”操作符(operator:"Exists",“存在”即可)来说明,该pod能够容忍所有以foo为键的taint,才能让这个pod运行在该master节点上。
apiVersion: v1
kind: Pod
...
spec:
tolerations:
- key: "foo"
operator: "Exists"
effect: "NoSchedule"
当然,如果就是像要一个单节点的k8s,删除这个taint才是正确的选择,操作如下:
kubectl taint nodes --all node-role.kubernetes.io/master-
在“node-role.kubernetes.io/master”这个键后面加上了一个短横线"-",这个格式就意味着移除所有以“node-role.kubernetes.io/master”为键的taint
- 部署worker节点
node节点执行刚才获取的命令
# kubeadm join 192.168.1.170:6443 --token gpy810.gaq18z5bnks9occf \
--discovery-token-ca-cert-hash sha256:747559b3a32db293cd063a77559c85d04469026145d99cf97fe4fac002717512
查看节点信息
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master.k8s.com Ready master 38m v1.15.1
node.k8s.com Ready <none> 34m v1.15.1
有了kubeadm这样的原生管理工具,k8s的部署已经被大大简化,更重要的是,像证书、授权、各个组件的配置等部署中最麻烦的操作,kubeadm都已经帮忙完成了。
至此,整个k8s集群就部署完成了,可以使用命令行的方式进行应用的发布和管理了,但是用起来可能不是很爽,下面就介绍下k8s的dashboard的部署方式。
- 部署dashboard可视化插件
在k8s社区中,又一个很受欢迎的dashboard项目,它可以给用户提供一个可视化的web界面来查看当前集群的各种信息,毫不意外,它的部署也相当简单。
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml
部署完成后我们可以查看dashboard的pod状态。
# kubectl get pods -n kube-system
kubernetes-dashboard-6f9887bccc-qc47t 1/1 Running 1 11d
需要注意的是,由于dashboard是一个web server,很多人经常会在自己的公有云上无意地暴露dashborad的端口,从而造成安全隐患,所以,1.7版本之后的dashboard部署完成后,默认只能通过proxy的方式在本地访问,具体操作,可以查看dashboard的官方文档。
而如果想从集群外访问这个dashboard的话,就需要用到ingress。
- 部署容器存储插件
很多时候我们需要用数据卷(volume)把外面宿主机上的目录或者文件挂载进容器的mount namespace中,从而达到容器和宿主机共享这些目录或文件的目的,容器里的应用就可以在这些数据卷中新建和写入文件了。
可是,如果在某一台机器上启动一个容器,显然无法看到其他机器上的容器在它们的数据卷里写入的文件,这就是容器最典型的特征之一:无状态
而容器的持久化存储,就是用来保存容器存储状态的重要手段,存储插件会在容器里挂载一个基于网络或其他机制的远程数据卷,使得在容器里创建的文件,实际上保存在远程存储服务器上,或者以分布式的方式保存在多个节点上,而与当前宿主机没有任何绑定关系,这样无论在其他哪个宿主机上启动新的容器,都可以请求挂载指定的持久化存储卷,从而访问到数据卷里的的数据,这就是"持久化"的含义。
由于k8s本身的松耦合设计,绝大多数存储项目,如ceph、glusterfs、nfs等,都可以为k8s提供持久化存储能力,在这次的部署实战中,选择了rook插件进行存储的部署实验。
rook是一个基于ceph的k8s存储插件(它后期也在加入对更多存储实现的支持),不同ceph的简单封装,rook在自己的实现中加入了水平扩展、迁移、灾难备份、监控等大量的企业级功能,使得这个项目变成了一个完整的,生产级别可用的容器存储插件。
得益于容器化技术,以下三条命令就可以将rook部署起来,如下:
# kubectl apply -f https://raw.githubusercontent.com/rook/rook/master/cluster/examples/kubernetes/ceph/common.yaml
# kubectl apply -f https://raw.githubusercontent.com/rook/rook/master/cluster/examples/kubernetes/ceph/operator.yaml
# kubectl apply -f https://raw.githubusercontent.com/rook/rook/master/cluster/examples/kubernetes/ceph/cluster.yaml
在部署完成后,就可以看到rook项目会将自己的pod放置在由它自己管理的namespace当中,如下:
# kubectl get pod -n rook-ceph
NAME READY STATUS RESTARTS AGE
csi-cephfsplugin-provisioner-7c85779954-cz7g4 4/4 Running 0 5m11s
csi-cephfsplugin-provisioner-7c85779954-dmcq2 4/4 Running 0 5m11s
csi-cephfsplugin-th86r 3/3 Running 0 5m11s
csi-rbdplugin-provisioner-5474976bf6-6vx2n 5/5 Running 0 5m11s
csi-rbdplugin-provisioner-5474976bf6-lnr4t 5/5 Running 0 5m11s
csi-rbdplugin-sb6qj 3/3 Running 0 5m11s
rook-ceph-agent-rx7jf 1/1 Running 0 5m13s
rook-ceph-detect-version-fww7w 0/1 Terminating 0 11s
rook-ceph-operator-b947787bc-b2kvd 1/1 Running 0 7m10s
rook-discover-rc59k 1/1 Running 0 5m13s
这样,一个基于rook持久化存储集群就以容器的方式运行起来了,而接下来在k8s上创建的所有pod就能够通过persistent volume(PV)和persistent volume claim(pvc)的方式,在容器里挂载由ceph提供的数据卷里。
而rook则会负责这些数据卷的生命周期管理、灾难备份等运维工作。
选择rook其实是因为这个项目很有前途,如果去研究下rook项目的实现,就会发现它巧妙地依赖了k8s提供等编排能力,合理的使用了很多诸如operator、CRD等重要的扩特性,这使得rook成为了目前社区中机遇k8s api构建的最完善也最成熟的容器存储插件,可以想象,应该很快就会得到整个社区的推崇。