Kubernetes解决了诸多运维难题,是目前主流的基础架构平台,也是容器编排领域的事实标准,可谓“天不生Kubernetes,运维万古如长夜”。如此流行的Kubernetes,该如何掌握、又该如何应用到生产中呢?本系列文章会详细讲述。
一 主要技术点
- Kubernetes集群介绍
- 部署高可用Kubernetes集群
- 部署应用程序
- 公开应用程序
- 更新应用程序
- 集群中的日志收集与监控
- Istio流量治理
- 基于Kubernetes的CI/CD
- ...
通过本系列文章,你将能够使用Kubeadm和Binary方式部署高可用的Kubernetes集群,了解集群中的一些名词及概念,在集群上部署容器化应用程序,并调试、扩容、更新、对外发布这些程序,实现流量治理,轻松搞定蓝绿发布、AB测试、金丝雀发布等集群相关功能。
二 Kubernetes集群介绍
Kubernetes协调高度可用的计算机集群,这些计算机作为一个单元连接在一起工作。Kubernetes允许将容器化的应用程序部署到集群中,且不是传统的绑定到单个机器上。为了利用这种新的部署模型,应用程序需要以一种将它们与单个主机分离的方式打包——容器化。在传统的部署模型中,应用程序直接安装到特定的机器上,与主机深度集成,与传统部署模型相比,容器化的应用程序更加灵活可用。Kubernetes以更有效的方式在集群中自动化分发和调度应用程序容器。
Kubernetes集群由两种资源类型组成:Master和Node:
- Master协调集群工作,组件有:
- 使用二进制运行Kubernetes集群的时候,在Master上这三个是可选组件
- kube-apiserver:对外提供操作和获取Kubernetes资源的API,是集群中唯一操作ETCD的组件
- kube-controller-manager:集群状态的维护者,观察集群的实际状态,并与ETCD中的预期状态进行对比,让两者达到最终一致
- kube-scheduler:Kubernetes的大脑,调度新应用的发布请求,决策发布在哪些节点上
- docker、kubelet和kube-proxy
- 网络插件,本环境使用的calico
- Node运行应用程序,包含的组件:
- kubelet:与API Server交互,接收指令、启动Pod、关闭Pod
- kube-proxy:对Pod进行寻址,实现负载均衡和服务发现
- docker:Kubernetes集群中的一种容器运行时
- 网络插件,本环境使用的calico
同时Kubernetes将集群中的网络配置及对象的状态信息存储在ETCD集群中,所以还需要一套ETCD集群。
三 部署高可用Kubernetes集群
Kubernetes集群是一个功能丰富但有些复杂的系统,不过亲自运行一个系统永远是学习它的最佳开始。
本篇文章是该系列文章的开篇,主要介绍Kubernetes高可用集群的两种主流安装方式:Kubeadm和二进制(这两种安装方式各有优劣,至于生产环境中采用何种方式部署集群,亦或是使用云平台提供的Kubernetes集群,还需根据实际情况选择),以及部署Kubernetes的主要插件。
不论是Kubeadm还是二进制的方式安装Kubernetes集群,都要先初始化安装环境。
3.1 安装环境介绍
以下主机列表是我介绍两种安装方式时使用的主要资源:
- 操作系统:CentOS7.x
- 主机角色: Kubeadm环境主机列表: 主机名IP地址VIPCPU内存角色lb01192.168.0.3192.168.0.111>=1>=2GHaproxyKeepAlive MASTERlb02192.168.0.5192.168.0.111>=1>=2GHaproxyKeepAlive BACKUPkm01192.168.0.11 >=2>=2GMaster/Ansiblekm02192.168.0.12 >=2>=2GMasterkm03192.168.0.13 >=2>=2GMasterkn01192.168.0.21 >=2>=2GNodekn02192.168.0.22 >=2>=2GNode二进制环境主机列表: 主机名IP地址VIPCPU内存角色lb01192.168.0.3192.168.0.111>=1>=2GHaproxyKeepAlive MASTERlb02192.168.0.5192.168.0.111>=1>=2GHaproxyKeepAlive BACKUPkm01.aiops.red192.168.0.16 >=2>=2GMaster/ETCD/Ansiblekm02.aiops.red192.168.0.17 >=2>=2GMaster/ETCDkm03.aiops.red192.168.0.18 >=2>=2GMaster/ETCDkn01.aiops.red192.168.0.23 >=2>=2GNodekn02.aiops.red192.168.0.24 >=2>=2GNode
- 软件列表:Kubernetes v1.17. :包括了Kubernetes集群所有的相关组件ETCD v3.3.18 :存储Kubernetes状态信息 Docker v19.03.4:Kubernetes中的容器运行时,也是1.17. 官方建议的Docker版本 HaProxy:负载均衡器,Kubernetes集群中Kube-apiserver的流量入口和负载均衡 KeepAlived:高可用工具,负责HaProxy的高可用 Ansible:配置管理工具,减少安装Kubernetes高可用集群时机械化的重复工作,减少工作量,但不会影响你对Kubernetes系统的认识
3.2 集群安装前的准备
对Kubernetes集群环境初始化,需要在集群中的各个节点执行大量相同的命令,为了减少机械、廉价的重复性工作,也为了让读者将更多的心思用到Kubernetes高可用集群本身,我这里采用了简单易上手的Ansible配置管理工具进行初始化工作。
3.2.1 安装配置Ansible
- 如果你的环境中没有Ansible,可通过以下命令安装。了解Ansible更多用法,可以查阅我的另一篇文章配置管理工具之Ansible:
[root@km01 ~]# yum -y install ansible
# 如果提示没有这个安装包,则需要安装epel-releas源,然后再次安装ansible
[root@km01 ~]# yum -y install epel-release
- 配置目标主机,在/etc/ansible/hosts文件中新增三个分组:k8sm组,Kubernetes集群的所有Master;k8sn组:Kubernetes集群中的所有Node;k8sall组:Kubernetes集群中所有主机:
[root@km01 ~]# vim /etc/ansible/hosts
[k8sm]
192.168.0.[11:13]
[k8sn]
192.168.0.[21:22]
[k8sall:children]
k8sm
k8sn
- 配置免密登录
[root@km01 ~]# ssh-keygen -t rsa
[root@km01 ~]# ssh-copy-id 192.168.0.11
[root@km01 ~]# ssh-copy-id 192.168.0.12
...
[root@km01 ~]# ssh-copy-id 192.168.0.22
- 验证 完成以上配置,就可以通过Ansible管理三个分组中的主机进了。在操作前,可以先验证下配置的正确性:
[root@km01 ~]# ansible k8sall -m ping
3.2.2 集群环境初始化(Kubernetes集群中的主机都要执行)
- 修改主机名: 各主机名不能重复,且集群中的主机可以通过主机名互相访问
- [root@km01 ~]# hostnamectl set-hostname <hostname> # 以Kubeadm环境的hosts文件举例 [root@km01 ~]# cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.0.11 km01 192.168.0.12 km02 192.168.0.13 km03 192.168.0.21 kn01 192.168.0.22 kn02
- 设置系统参数
- 安装docker及创建daemon.json文件
- 修改系统时区为Asia/Shanghai
- 关闭swap
- 关闭防火墙、关闭selinux、重置iptables
- 更新yum源并安装依赖包
2-7步均通过Ansible Playbook实现,Playbook文件我已上传到GitHub,囿于篇幅,这里就不再展开文件内容。项目地址 https://github.com/weiwendi/k8sdeploy,把k8sdeploy
项目拉取到ansible所在的主机上:
[root@km01 ~]# git clone https://github.com/weiwendi/k8sdeploy.git
[root@km01 ~]# cd k8sdeploy/initialize
[root@km01 initialize]# ansible-playbook installPackages.yaml
[root@km01 initialize]# ansible-playbook initEnv.yaml
执行完这两个脚本,就完成了集群环境初始化。
3.2.3 k8sdeploy项目介绍
k8sdeploy项目下有七个子目录:addons、app、binary、haproxy、initialize、keepalived、kubeadm,顾名思义,每个目录都有其相关功能:
- addons:Kubernetes集群的相关插件,在集群安装完成后,为了更好的管理集群。
- calico:网络插件, 集群安装完成后,需要执行此目录中的文件;
- coredns:DNS服务,使用二进制包安装完成集群后,需要执行此目录中的文件;
- dashboard:集群部署完成后,执行此目录中的文件安装UI控制台;
- ingress-nginx:将集群内的服务发布到集群外。
- app:介绍部署应用程序时,使用到的程序。
- binary:二进制包安装Kubernetes集群所需的Ansible Playbook脚本及依赖的文件,相关目录有:
- pki:生成证书需要的文件;
- deployEtcd:安装ETCD集群的脚本及相关文件,二进制环境需要自己部署ETCD;
- deployApiServer:安装Kube-apiserver组件的脚本及相关文件;
- deployControllerManager:安装Kube-controller-manager组件的脚本及相关文件;
- deployScheduler:安装Kube-scheduler组件的脚本及相关文件;
- deployKubelet:安装Kubelet组件的脚本及相关文件;
- deployKubeProxy:安装Kubeproxy组件的脚本及相关文件;
- initialize:用来执行Kubernetes集群环境的初始化,包含两个Ansible Playbook文件(installPackages.yaml和initEnv.yaml)和一个config目录。
- installPackages.yaml:用来安装依赖包,实现了集群环境初始化的第2和6步,需要先执行此文件;
- initEnv.yaml:实现了集群环境初始化中的第3、4、5、7步;
- config:目录里是Ansible Playbook依赖的配置文件,有docker的daemon.json文件和系统参数文件;
- 使用方法:
cd k8sdeploy/initialize # 安装的依赖包比较多,这个过程会比较慢 ansible-playbook installPackages.yaml ansible-playbook initEnv.yaml
- kubeadm:Kubeadm工具安装高可用Kubernetes集群所需的文件:
- installKubeadm.yaml:用来安装kubeadm、kubelet和kubectl
- config:Kubernetes相关的yum源文件
- kubernetes:kubeadm安装Kubernetes集群的配置文件
- 使用方法:
cd k8sdeploy/kubeadm ansible-playbook installKubeadm.yam
- haproxy:HaProxy的配置文件,可直接拷贝:
- 使用方法:
cp k8sdeploy/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg
- keepalived:包含两个keepalived配置文件,一主一备需按角色拷贝,还包含一个检测脚本,检测到HaProxy异常时实现Keepalived的主从切换:
- 使用方法:
# keepalived master node cp k8sdeploy/keepalived/master-keepalived.conf /etc/keepalived/keepalived.conf cp k8sdeploy/keepalived/checkHaproxy.sh /etc/keepalived/checkHaproxy.sh # keepalived backup node cp k8sdeploy/keepalived/backup-keepalived.conf /etc/keepalived/keepalived.conf cp k8sdeploy/keepalived/checkHaproxy.sh /etc/keepalived/checkHaproxy.sh
3.4 高可用环境配置
Kubernetes作为重要的容器治理平台,保障其自身高可靠稳定运行尤为重要,这需要我们从三方面考虑:
- ETCD:ETCD存储Kubernetes集群的状态信息,我们需要把ETCD部署为高可用集群。
- 管理层服务:kube-scheduler和kube-controller-manager都属于管理层服务,使用一主多从的高可用方案,在同一时刻只允许一个服务处理具体的任务。Kubernetes中实现了一套简单的选主逻辑,依赖Etcd实现scheduler和controller-manager的选主功能。
- Kube-apiserver:Kubernetes的接入层服务主要是kube-apiserver。kube-apiserver本身是无状态的,它的主要任务是把资源数据存储到Etcd中,后续具体的业务逻辑由kube-scheduler和kube-controller-manager执行。 可以同时启动多个kebu-apiserver服务,通过HaProxy进行流量负载,使用Keepalived负责HaProxy的高可用。
3.4.1 部署HaProxy
HaProxy是一个使用C语言编写的自由及开放源代码软件,提供高可用性、负载均衡,以及基于TCP和HTTP的应用程序代理,并能对后端服务进行健康监测,把流量转发给健康的后端。
在准备好的两台主机(lb01、lb02)上执行以下操作:
- 安装HaProxy:
yum install -y haproxy
- 修改haproxy.cfg配置文件:
git clone https://github.com/weiwendi/k8sdeploy.git
cp k8sdeploy/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg
在haproxy.cfg文件中,有几处配置需要根据实际环境修改:
- frontend中监听的端口,此端口是通过VIP访问Kube-apiserver的端口
- backend中对应server的IP,此IP是Kubernetes Master主机的IP,端口为Kube-apiserver的端口
- 修改日志输出:
默认HaProxy的日志输出在/var/log/messages文件中,为了便于查看及管理,我们把它输出到/var/log/haproxy/haproxy.log文件中:
代码语言:javascript复制# 修改/etc/sysconfig/rsyslog文件为如下内容
cat /etc/sysconfig/rsyslog
SYSLOGD_OPTIONS="-r"
# 修改/etc/rsyslog.conf文件
vim /etc/rsyslog.conf
# 取消以下选项的注释:
$ModLoad imudp
$UDPServerRun 514
#增加以下内容:
# haproxy -r 2
local2.* /var/log/haproxy/haproxy.log
- 重启服务:
systemctl restart rsyslog
systemctl start haproxy
3.4.2 部署Keepalived
Keepalived是一个使用C语言编写的自由及开放源代码软件。主要为Linux系统和基于Linux的基础设施提供简单而健壮的高可用性工具,通过VRRP协议实现。
在准备好的两台主机上(lb01、lb02)执行以下操作:
- 安装Keepalived:
yum install -y keepalived
- 修改/etc/keepalived/keepalived.conf配置文件: 配置文件分为主配置文件和备配置文件,需根据主机角色分发:
[root@lb01 ~]# cp k8sdeploy/keepalived/master-keepalived.conf /etc/keepalived/keepalived.conf
[root@lb02 ~]# cp k8sdeploy/keepalived/backup-keepalived.conf /etc/keepalived/keepalived.conf
配置文件中有一些选项需要根据实际环境修改:
- notification_email定义的邮箱地址,填写主从切换后接受报警的邮箱
- notification_email_from 发送主从切换警报的邮箱
- smtp_server 发件邮箱使用的smtp服务器
- interface eth0 绑定VIP地址的网卡名称
- virtual_ipaddress 填写你实际使用的VIP地址
- 拷贝健康检查文件到主备节点,并确保对该文件有执行权限:
cp k8sdeploy/keepalived/checkHaproxy.sh /etc/keepalived/checkHaproxy.sh
chmod x /etc/keepalived/checkHaproxy.sh
- 修改输出日志文件: 默认Keepalived的日志会打印在/var/log/messages文件中,为了方便查看和管理,我们把它的日志内容输出到/var/log/keepalived/keepalived.log中。
# /etc/sysconfig/keepalived文件内容修改如下:
cat /etc/sysconfig/keepalived
KEEPALIVED_OPTIONS="-D -d -S 0"
# 在/etc/rsyslog.conf文件中增加如下内容:
vim /etc/rsyslog.conf
# keepalived -S 0
local0.* /var/log/keepalived/keepalived.log
- 重启服务:
# 重启rsyslog服务
systemctl restart rsyslog
# 启动keepalived(先启动主,再启动从)
systemctl start keepalived
- 在主节点上查看VIP的是否绑定成功:
[root@lb01 ~]# ip addr
到这里,准备环境已经完成,接下来,进入Kubernetes高可用集群的安装。
可以手动停止主节点的HaProxy服务,验证VIP是否自动漂移到从节点。
3.5 通过Kubeadm安装高可用Kubernetes集群
Kubeadm方式安装Kubernetes集群的过程相对简单,除kubelet外,其他组件均以容器的方式运行,并且支持高可用部署,我们无需考虑ETCD及控制层面的高可用,只需保证在HaProxy中配置了Kube-apiserver的流量负载。
3.5.1 安装kubeadm、kubelet及kubectl
进入k8sdeploy项目的kubeadm目录,执行installKubeadm.yaml安装kubeadm、kubelet和kubectl:
代码语言:javascript复制[root@km01 ~]# cd k8sdeploy/kubeadm
[root@km01 kubeadm]# ansible-playbook installKubeadm.yaml
3.5.2 使用kubeadm安装Kubernetes高可用集群
安装完kubeadm工具后,就可以使用该工具安装Kubernetes集群了,我已经创建好了安装Kubernetes集群时依赖的配置文件,但有几个配置项需要根据实际环境修改:
- dnsDomain: 服务可用域,默认是cluster.local,该配置文件中定义的是aiops.red
- podSubnet:Pod网络
- serviceSubnet: Service网络
- imageRepository: 集群使用的镜像仓库,默认是k8s.gcr.io,可以使用我的阿里云镜像仓库,已经准备好了所需的镜像,地址是registry.cn-hangzhou.aliyuncs.com/weiwendi
[root@km01 ~]# cd k8sdeploy/kubeadm/kubernetes/
[root@km01 kubernetes]# kubeadm init --config=kubeadm-config.yaml --upload-certs
命令执行完成,终端上会打印很多内容,把类似下面的这段输出拷贝出来:
代码语言:javascript复制Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of the control-plane node running the following command on each as root:
kubeadm join 192.168.0.111:16443 --token 2yzik9.g5tlnr5cr0ocdcr0
--discovery-token-ca-cert-hash sha256:3327709183ac204ca1e3e986d9c311a6222d904070c72ee1260a707d9c5d1810
--control-plane --certificate-key c672459d595fce1b563e3150e342b692fb4df3a61b51ecd634f05fea5c1a9110
Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.0.111:16443 --token 2yzik9.g5tlnr5cr0ocdcr0
--discovery-token-ca-cert-hash sha256:3327709183ac204ca1e3e986d9c311a6222d904070c72ee1260a707d9c5d1810
...
3.5.3 配置kubectl
按照输出内容,配置Kubernetes集群的命令行管理工具kubectl:
代码语言:javascript复制[root@km01 ~]# mkdir -p $HOME/.kube
[root@km01 ~]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
3.5.4 配置集群网络
实现Kubernetes集群网络的方案很多,Calico工具就实现了一个很优秀的Kubernetes集群网络解决方案:
代码语言:javascript复制[root@km01 ~]# cd k8sdeploy/addons/calico/
[root@km01 calico]# kubectl apply -f calico.yaml
calico.yaml文件中也有两处配置需要注意:
- CALICO_IPV4POOL_CIDR:该字段的value定义Pod网段,要和kubeadm-config.yaml中的podSubnet字段值一致。
- image:要确保文件中的镜像仓库是可以访问的
3.5.5 为Kubernetes集群添加Master
输出内容中提示了如何将新的Master加入集群,粘贴并在目标主机执行:
代码语言:javascript复制# Master2
[root@km02 ~]# kubeadm join 192.168.0.111:16443 --token 2yzik9.g5tlnr5cr0ocdcr0
--discovery-token-ca-cert-hash sha256:3327709183ac204ca1e3e986d9c311a6222d904070c72ee1260a707d9c5d1810
--control-plane --certificate-key c672459d595fce1b563e3150e342b692fb4df3a61b51ecd634f05fea5c1a9110
# Master3
[root@km02 ~]# kubeadm join 192.168.0.111:16443 --token 2yzik9.g5tlnr5cr0ocdcr0
--discovery-token-ca-cert-hash sha256:3327709183ac204ca1e3e986d9c311a6222d904070c72ee1260a707d9c5d1810
--control-plane --certificate-key c672459d595fce1b563e3150e342b692fb4df3a61b51ecd634f05fea5c1a9110
3.5.6 为Kubernetes集群添加Node
输出内容中同样提示了如何将Node加入集群,粘贴并在目标主机执行:
代码语言:javascript复制# Node1
[root@kn01 ~]# kubeadm join 192.168.0.111:16443 --token 2yzik9.g5tlnr5cr0ocdcr0
--discovery-token-ca-cert-hash sha256:3327709183ac204ca1e3e986d9c311a6222d904070c72ee1260a707d9c5d1810
# Node2
[root@kn02 ~]# kubeadm join 192.168.0.111:16443 --token 2yzik9.g5tlnr5cr0ocdcr0
--discovery-token-ca-cert-hash sha256:3327709183ac204ca1e3e986d9c311a6222d904070c72ee1260a707d9c5d1810
3.5.7 查看集群各组件的可用性
集群安装完成了,可以使用命令查看组件的运行状态:
代码语言:javascript复制# 查看集群状态
[root@km01 ~]# kubectl get cs
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health":"true"}
[root@km01 ~]# curl -k https://192.168.0.111:16443/healthz
ok
# 查看集群中的主机
[root@km01 ~]# kubectl get nodes
3.5.8 部署Dashboard
Dashboard 是基于网页的 Kubernetes 用户界面。可以使用 Dashboard 将容器应用部署到 Kubernetes 集群中,也可以对容器应用排错,还能管理集群资源。可以使用 Dashboard 获取运行在集群中的应用的概览信息,也可以创建或者修改 Kubernetes 资源(如 Deployment,Job,DaemonSet 等等)。例如,可以对 Deployment 实现弹性伸缩、发起滚动升级、重启 Pod 或者使用向导创建新的应用。
我在k8sdeploy/addons/dashboard/目录下已经准备好了部署Dashboard的yaml文件,端口类型为NodePort,监听TCP30000端口,如果你集群中各主机的30000端口已被占用,请修改此文件的NodePort值及HaProxy配置文件中的对应端口号:
代码语言:javascript复制[root@km01 ~]# cd k8sdeploy/addons/dashboard/
[root@km01 dashboard]# kubectl apply -f dashboard.yaml
# 查看dashboard的运行情况
[root@km01 dashboard]# kubectl get pods -n kubernetes-dashboard
[root@km01 dashboard]# kubectl get services -n kubernetes-dashboard
Dashboard部署完成后,在浏览器中输入https://vip:17443访问,因为用的是IP地址,而Dashboard又不支持HTTP,所以会提示证书问题,点击“高级”按钮,点击“继续访问”。登录时的验证方式有Kubeconfig和token两种,建议采用token方式。查看token:
代码语言:javascript复制[root@km01 ~]# kubectl get secret -n kubernetes-dashboard
[root@km01 ~]# kubectl describe secret kubernetes-dashboard-token-ddxbs -n kubernetes-dashboard
这就是使用Kubeadm部署高可用Kubernetes集群的相关步骤,整个过程还是很简单的。接下来介绍使用二进制包部署高可用Kubernetes集群。
拷贝token字段的值,粘贴进浏览器的验证框,点击“登录”按钮。
3.6 通过二进制包安装高可用Kubernetes集群
采用二进制包安装相比Kubeadm会复杂一些,但维护相对简单。
3.6.1 创建集群所需证书及密钥
- 安装cfssl命令,用以生成证书及密钥:
[root@km01 ~]# wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O /usr/local/bin/cfssl
[root@km01 ~]# wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O /usr/local/bin/cfssljson
[root@km01 ~]# chmod x /usr/local/bin/cfssl*
[root@km01 ~]# cfssl version
- 生成根证书和私钥 根证书是集群所有节点共享的,只需要创建一个CA证书,签名后续创建的所有证书:
[root@km01 ~]# cd k8sdeploy/binary/pki
[root@km01 pki]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca
# 生成的ca-key.pem和ca.pem便是我们需要的密钥和证书
[root@km01 pki]# ls
ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem
# 将ca-key.pem和ca.pem拷贝到每个主节点的/etc/kubernetes/pki/目录
# 创建/etc/kubernetes/pki/目录
[root@km01 pki]# ansible k8sm -m file -a 'dest=/etc/kubernetes/pki/ state=directory'
# 拷贝文件
[root@km01 pki]# scp *.pem 192.168.0.16:/etc/kubernetes/pki/
[root@km01 pki]# scp *.pem 192.168.0.17:/etc/kubernetes/pki/
[root@km01 pki]# scp *.pem 192.168.0.18:/etc/kubernetes/pki/
3.6.2 二进制包下载
Kubernetes1.17.0相关的二进制包我上传在了百度网盘,链接:https://pan.baidu.com/s/1sMyqWZCwzAEHuCZAmREKJg,提取码:6jr2
,保存到/tmp目录下:
[root@km01 ~]# wget -P /tmp/ https://dl.k8s.io/v1.17.0/kubernetes-server-linux-amd64.tar.gz
[root@km01 ~]# tar zxf /tmp/kubernetes-server-linux-amd64.tar.gz -C /tmp/
需要将这些包解压到Ansible节点的/tmp目录,方便包分发。
ETCD3.3.18的官方GitHub下载地址:
代码语言:javascript复制[root@km01 ~]# wget -P /tmp/ https://github.com/etcd-io/etcd/releases/download/v3.3.18/etcd-v3.3.18-linux-amd64.tar.gz
[root@km01 ~]# tar zxf /tmp/etcd-v3.3.18-linux-amd64.tar.gz -C /tmp/
3.6.3 部署ETCD集群
在k8sdeploy/binary/deployEtcd/目录中,已经准备好了自动部署ETCD集群的Ansible脚本。
- 生成ETCD证书及私钥:
[root@km01 ~]# cd k8sdeploy/binary/pki/etcd
[root@km01 etcd]# cfssl gencert -ca=../ca.pem -ca-key=../ca-key.pem -config=../ca-config.json -profile=kubernetes etcd-csr.json | cfssljson -bare etcd
[root@km01 etcd]# ls etcd*.pem
这些证书及私钥需要拷贝到ETCD节点的/etc/kubernetes/pki/目录中,已在Ansible脚本里实现,无需手动拷贝。
- 进入k8sdeploy/binary/deployEtcd目录,执行deployEtcd.yaml,完成ETCD集群的部署:
[root@km01 deployEtcd]# ansible-playbook deployEtcd.yaml
# 查看ETCD节点信息
[root@km01 deployEtcd]# etcdctl --ca-file=/etc/kubernetes/pki/ca.pem --cert-file=/etc/kubernetes/pki/etcd.pem --key-file=/etc/kubernetes/pki/etcd-key.pem member list
3.6.4 部署Kube-apiserver服务
- 生成kube-apiserver所需的证书和私钥: 下面的命令生成kubernetes.pem和kubernetes-key.pem,需要把这两个文件拷贝到所有Master主机的/etc/kubernetes/pki目录里:
[root@km01 ~]# cd k8sdeploy/binary/pki/api-server
[root@km01 api-server]# cfssl gencert -ca=../ca.pem
-ca-key=../ca-key.pem
-config=../ca-config.json -profile=kubernetes
kubernetes-csr.json | cfssljson -bare kubernetes
- 进入k8sdeploy/binary/deployApiServer目录执行部署脚本:
[root@km01 ~]# cd k8sdeploy/binary/deployApiServer
[root@km01 deployApiServer]# ansible-playbook deployApiServer.yaml
3.6.5 检查高可用环境的运行状态
3.4节配置了高可用集群,在浏览器中访问http://192.168.0.111/admin?stats页面,,查看Kube-apiserver的运行状态,需要把192.168.0.111替换为你的VIP地址。也可以手动停止主HaProxy,验证VIP是否漂移,在此过程中,执行以下命令,看结果是否不同:
代码语言:javascript复制curl -k https://192.168.0.17:6443
3.6.6 安装Kubectl
kubectl可以安装在连通Kubernetes集群的任一主机上,本环境在192.168.0.16Master主机上。
- 拷贝kubectl命令,并创建配置文件所需的目录:
[root@km01 ~]# cp -a /tmp/kubernetes/server/bin/kubectl /usr/local/bin/
[root@km01 ~]# mkdir ~/.kube
- 创建证书和私钥:
[root@km01 ~]# cd k8sdeploy/binary/pki/kubectl
[root@km01 kubectl]# cfssl gencert -ca=../ca.pem
-ca-key=../ca-key.pem -config=../ca-config.json
-profile=kubernetes
admin-csr.json | cfssljson -bare admin
- 创建kubeconfig配置文件: kubeconfig 为 kubectl 的配置文件,包含访问 kube-apiserver 所需的信息,如 kube-apiserver 地址、CA 证书和自身使用的证书:
# 设置集群参数,--server的地址是VIP的地址及端口
[root@km01 kubectl]# kubectl config set-cluster kubernetes
--certificate-authority=../ca.pem
--embed-certs=true
--server=https://192.168.0.111:16443
--kubeconfig=kube.config
# 设置客户端认证参数
[root@km01 kubectl]# kubectl config set-credentials admin
--client-certificate=admin.pem
--client-key=admin-key.pem
--embed-certs=true
--kubeconfig=kube.config
# 设置上下文参数
[root@km01 kubectl]# kubectl config set-context kubernetes
--cluster=kubernetes
--user=admin
--kubeconfig=kube.config
# 设置默认上下文
[root@km01 kubectl]# kubectl config use-context kubernetes --kubeconfig=kube.config
# 将kube.config文件拷贝到~/.kube/目录
[root@km01 kubectl]# cp kube.config ~/.kube/config
- 赋权,授予 kubernetes 证书访问 kubelet API 的权限: 在执行kubectl exec、run、logs等命令时,kube-apiserver会将请求转发到kubelet。这里定义 RBAC 规则,授权kube-apiserver 调用kubelet API:
[root@km01 kubectl]# kubectl create clusterrolebinding kube-apiserver:kubelet-apis
--clusterrole=system:kubelet-api-admin --user kubernetes
- 验证:
# 查看集群信息
[root@km01 kubectl]# kubectl cluster-info
[root@km01 kubectl]# kubectl get all --all-namespaces
[root@km01 kubectl]# kubectl get componentstatuses
3.6.7 部署Kube-controller-manager服务
- 生成kube-controller-manager所需的证书及私钥:
[root@km01 ~]# cd k8sdeploy/binary/pki/kube-controller-manager
[root@km01 kube-controller-manager]# cfssl gencert -ca=../ca.pem
-ca-key=../ca-key.pem -config=../ca-config.json
-profile=kubernetes kube-controller-manager-csr.json | cfssljson
-bare controller-manager
[root@km01 kube-controller-manager]# ls controller-manager*
controller-manager.csr controller-manager-key.pem controller-manager.pem
生成的三个文件需要拷贝到每个Master主机,该步骤已包含在Ansible Playbook文件中。
- 创建kube-controller-manager的配置文件kubeconfig
# 创建kubeconfig
[root@km01 kube-controller-manager]# kubectl config set-cluster kubernetes
--certificate-authority=../ca.pem --embed-certs=true
--server=https://192.168.0.111:16443
--kubeconfig=kube-controller-manager.kubeconfig
root@km01 kube-controller-manager]# kubectl config set-credentials
system:kube-controller-manager --client-certificate=controller-manager.pem
--client-key=controller-manager-key.pem --embed-certs=true
--kubeconfig=kube-controller-manager.kubeconfig
[root@km01 kube-controller-manager]# kubectl config set-context
system:kube-controller-manager --cluster=kubernetes
--user=system:kube-controller-manager
--kubeconfig=kube-controller-manager.kubeconfig
[root@km01 kube-controller-manager]# kubectl config use-context
system:kube-controller-manager
--kubeconfig=kube-controller-manager.kubeconfig
将kube-controller-manager.kubeconfig分发到所有Master主机,该步骤已包含在Ansible Playbook文件中。
- 进入k8sdeploy/binary/deployControllerManager执行部署脚本:
[root@km01 deployControllerManager]# ansible-playbook deployControllerManager.yaml
3.6.8 部署Kube-scheduler服务
- 创建证书和私钥:
[root@km01 ~]# cd k8sdeploy/binary/pki/kube-scheduler
[root@km01 kube-scheduler]# cfssl gencert -ca=../ca.pem
-ca-key=../ca-key.pem -config=../ca-config.json
-profile=kubernetes kube-scheduler-csr.json | cfssljson
-bare kube-scheduler
- 创建scheduler的kubeconfig文件:
[root@km01 kube-scheduler]# kubectl config set-cluster kubernetes
--certificate-authority=../ca.pem --embed-certs=true
--server=https://192.168.0.111:16443
--kubeconfig=kube-scheduler.kubeconfig
[root@km01 kube-scheduler]# kubectl config set-credentials
system:kube-scheduler --client-certificate=kube-scheduler.pem
--client-key=kube-scheduler-key.pem --embed-certs=true
--kubeconfig=kube-scheduler.kubeconfig
[root@km01 kube-scheduler]# kubectl config set-context
system:kube-scheduler --cluster=kubernetes
--user=system:kube-scheduler
--kubeconfig=kube-scheduler.kubeconfig
[root@km01 kube-scheduler]# kubectl config use-context system:kube-scheduler --kubeconfig=kube-scheduler.kubeconfig
将kube-scheduler.kubeconfig分发到所有Master主机,该步骤已包含在Ansible Playbook文件中。
- 进入k8sdeploy/binary/deployScheduler执行部署脚本:
[root@km01 deployScheduler]# ansible-playbook deployScheduler.yaml
3.6.9 部署Kubelet服务
- 创建bootstrap配置文件
# 创建token
[root@km01 ~]# cd k8sdeploy/binary/pki/kubectl
[root@km01 kubectl]# export BOOTSTRAP_TOKEN=$(/tmp/kubernetes/server/bin/kubeadm token create
--description kubelet-bootstrap-token
--groups system:bootstrappers:worker
--kubeconfig kube.config)
# 设置集群参数
[root@km01 kubectl]# kubectl config set-cluster kubernetes
--certificate-authority=../ca.pem
--embed-certs=true
--server=https://192.168.0.111:6443
--kubeconfig=kubelet-bootstrap.kubeconfig
# 设置客户端认证参数
[root@km01 kubectl]# kubectl config set-credentials kubelet-bootstrap
--token=${BOOTSTRAP_TOKEN}
--kubeconfig=kubelet-bootstrap.kubeconfig
# 设置上下文参数
[root@km01 kubectl]# kubectl config set-context default
--cluster=kubernetes
--user=kubelet-bootstrap
--kubeconfig=kubelet-bootstrap.kubeconfig
# 设置默认上下文
[root@km01 kubectl]# kubectl config use-context default --kubeconfig=kubelet-bootstrap.kubeconfig
把生成的kubelet-bootstrap.kubeconfig文件拷贝到每个Node上,因为我们Master也安装了Kubelet,也需要拷贝到Master上。另外还需要把ca.pem证书拷贝到Node节点的/etc/kubernetes/pki目录中。
- 为bootstrap赋权
[root@km01 kubectl]# kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --group=system:bootstrappers
- 进入k8sdeploy/binary/deployKubelet目录执行部署脚本:
[root@km01 deployKubelet]# ansible-playbook deployKubelet.yaml
- Approve bootstrap请求:
[root@km01 ~]# kubectl get csr
[root@km01 ~]# kubectl certificate approve <name>
3.6.10 部署Kube-proxy服务
- 创建证书和私钥:
[root@km01 ~]# cd k8sdeploy/binary/pki/kube-proxy
[root@km01 kube-proxy]# cfssl gencert -ca=../ca.pem
-ca-key=../ca-key.pem -config=../ca-config.json
-profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
- 创建kube-proxy的kubeconfig文件
# 创建kube-proxy.kubeconfig
[root@km01 kube-proxy]# kubectl config set-cluster kubernetes
--certificate-authority=../ca.pem --embed-certs=true
--server=https://192.168.0.111:16443 --kubeconfig=kube-proxy.kubeconfig
[root@km01 kube-proxy]# kubectl config set-credentials kube-proxy
--client-certificate=kube-proxy.pem --client-key=kube-proxy-key.pem
--embed-certs=true --kubeconfig=kube-proxy.kubeconfig
[root@km01 kube-proxy]# kubectl config set-context default --cluster=kubernetes
--user=kube-proxy --kubeconfig=kube-proxy.kubeconfig
[root@km01 kube-proxy]# kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
- 进入k8sdeploy/binary/deployKubeProxy目录执行部署脚本:
[root@km01 deployKubeProxy]# ansible-playbook deployKubeProxy.yaml
3.6.11 安装CNI插件——Calico
代码语言:javascript复制[root@km01 ~]# cd k8sdeploy/addons/calico/
[root@km01 calico]# kubectl apply -f calico.yaml
3.6.12 安装CoreDNS
CoreDNS 是一个灵活可扩展的 DNS 服务器,可以作为 Kubernetes 集群 的DNS。与 Kubernetes 一样,CoreDNS 项目由 CNCF 持有。
代码语言:javascript复制[root@km01 ~]# cd k8sdeploy/addons/coredns/
[root@km01 calico]# kubectl apply -f coredns.yaml
3.6.13 安装DashBoard
代码语言:javascript复制[root@km01 ~]# cd k8sdeploy/addons/dashboard/
[root@km01 dashboard]# kubectl apply -f dashboard.yaml
3.6.14 集群可用性测试
我们已经正常运行了Calico、CoreDNS和DashBoard,但谨慎起见,可通过以下几项,验证集群可用性:
部署Nginx Deployment:
代码语言:javascript复制[root@km01 ~]# cd k8sdeploy/app/nginx
[root@km01 nginx]# kubectl apply -f nginx.yaml
- IP测试
# 测试pod ip的连通性
# 获取nginx pod的IP地址,在集群中任意节点上ping该IP
[root@km01 nginx]# kubectl get pod -o wide
# 测试service ip及nodePort的连通性
# 获取nginx service的IP和nodePort,在集群中任意节点上curl该地址
[root@km01 nginx]# kubectl get service
[root@km01 nginx]# curl http://serviceip
[root@km01 nginx]# curl http://nodeIP:nodePort
- 域名测试
使用kubectl exec命令登录nginx pod容器:
代码语言:javascript复制[root@km01 nginx]# kubectl exec -it nginx-85545d47d4-x8smd sh
# ping kubernetes
# ping nginx
# ping kube-dns.kube-system
# Kubernetes Service禁ping了,但能正确解析到域名的IP地址
Service的名称格式:service-name.namespace.svc.cluster.local。
Binary的安装也介绍完了,相比Kubeadm方式是不是复杂了很多,不过也没关系,我们已经搞定了。
接下来,介绍在Kubernetes集群中部署程序,以及生产中的常用操作。
文章转载自魏文弟。