天不生Kubernetes,运维万古如长夜|生产级K8s高可用集群实战一

2020-02-26 13:15:55 浏览数 (1)


Kubernetes解决了诸多运维难题,是目前主流的基础架构平台,也是容器编排领域的事实标准,可谓“天不生Kubernetes,运维万古如长夜”。如此流行的Kubernetes,该如何掌握、又该如何应用到生产中呢?本系列文章会详细讲述。

一 主要技术点

  1. Kubernetes集群介绍
  2. 部署高可用Kubernetes集群
  3. 部署应用程序
  4. 公开应用程序
  5. 更新应用程序
  6. 集群中的日志收集与监控
  7. Istio流量治理
  8. 基于Kubernetes的CI/CD
  9. ...

通过本系列文章,你将能够使用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 安装环境介绍

以下主机列表是我介绍两种安装方式时使用的主要资源:

  1. 操作系统:CentOS7.x
  2. 主机角色: 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
  3. 软件列表: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
  1. 如果你的环境中没有Ansible,可通过以下命令安装。了解Ansible更多用法,可以查阅我的另一篇文章配置管理工具之Ansible:
代码语言:javascript复制
[root@km01 ~]# yum -y install ansible

# 如果提示没有这个安装包,则需要安装epel-releas源,然后再次安装ansible
[root@km01 ~]# yum -y install epel-release
  1. 配置目标主机,在/etc/ansible/hosts文件中新增三个分组:k8sm组,Kubernetes集群的所有Master;k8sn组:Kubernetes集群中的所有Node;k8sall组:Kubernetes集群中所有主机:
代码语言:javascript复制
[root@km01 ~]# vim /etc/ansible/hosts
[k8sm]
192.168.0.[11:13]
[k8sn]
192.168.0.[21:22]
[k8sall:children]
k8sm
k8sn
  1. 配置免密登录
代码语言:javascript复制
[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
  1. 验证 完成以上配置,就可以通过Ansible管理三个分组中的主机进了。在操作前,可以先验证下配置的正确性:
代码语言:javascript复制
[root@km01 ~]# ansible k8sall -m ping
3.2.2 集群环境初始化(Kubernetes集群中的主机都要执行)
  1. 修改主机名: 各主机名不能重复,且集群中的主机可以通过主机名互相访问
  2. [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
  3. 设置系统参数
  4. 安装docker及创建daemon.json文件
  5. 修改系统时区为Asia/Shanghai
  6. 关闭swap
  7. 关闭防火墙、关闭selinux、重置iptables
  8. 更新yum源并安装依赖包

2-7步均通过Ansible Playbook实现,Playbook文件我已上传到GitHub,囿于篇幅,这里就不再展开文件内容。项目地址 https://github.com/weiwendi/k8sdeploy,把k8sdeploy项目拉取到ansible所在的主机上:

代码语言:javascript复制
[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文件和系统参数文件;
    • 使用方法:
    代码语言:javascript复制
    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集群的配置文件
    • 使用方法:
    代码语言:javascript复制
    cd k8sdeploy/kubeadm
    ansible-playbook installKubeadm.yam
  • haproxy:HaProxy的配置文件,可直接拷贝:
    • 使用方法:
    代码语言:javascript复制
    cp k8sdeploy/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg
  • keepalived:包含两个keepalived配置文件,一主一备需按角色拷贝,还包含一个检测脚本,检测到HaProxy异常时实现Keepalived的主从切换:
    • 使用方法:
    代码语言:javascript复制
    # 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)上执行以下操作:

  1. 安装HaProxy:
代码语言:javascript复制
yum install -y haproxy
  1. 修改haproxy.cfg配置文件:
代码语言:javascript复制
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的端口

  1. 修改日志输出:

默认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
  1. 重启服务:
代码语言:javascript复制
systemctl restart rsyslog
systemctl start haproxy
3.4.2 部署Keepalived

Keepalived是一个使用C语言编写的自由及开放源代码软件。主要为Linux系统和基于Linux的基础设施提供简单而健壮的高可用性工具,通过VRRP协议实现。

在准备好的两台主机上(lb01、lb02)执行以下操作:

  1. 安装Keepalived:
代码语言:javascript复制
yum install -y keepalived
  1. 修改/etc/keepalived/keepalived.conf配置文件: 配置文件分为主配置文件和备配置文件,需根据主机角色分发:
代码语言:javascript复制
[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地址

  1. 拷贝健康检查文件到主备节点,并确保对该文件有执行权限:
代码语言:javascript复制
cp k8sdeploy/keepalived/checkHaproxy.sh /etc/keepalived/checkHaproxy.sh
chmod  x /etc/keepalived/checkHaproxy.sh
  1. 修改输出日志文件: 默认Keepalived的日志会打印在/var/log/messages文件中,为了方便查看和管理,我们把它的日志内容输出到/var/log/keepalived/keepalived.log中。
代码语言:javascript复制
# /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
  1. 重启服务:
代码语言:javascript复制
# 重启rsyslog服务
systemctl restart rsyslog

# 启动keepalived(先启动主,再启动从)
systemctl start keepalived
  1. 在主节点上查看VIP的是否绑定成功:
代码语言:javascript复制
[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
代码语言:javascript复制
[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 创建集群所需证书及密钥
  1. 安装cfssl命令,用以生成证书及密钥:
代码语言:javascript复制
[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
  1. 生成根证书和私钥 根证书是集群所有节点共享的,只需要创建一个CA证书,签名后续创建的所有证书:
代码语言:javascript复制
[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目录下:

代码语言:javascript复制
[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脚本。

  1. 生成ETCD证书及私钥:
代码语言:javascript复制
[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脚本里实现,无需手动拷贝。

  1. 进入k8sdeploy/binary/deployEtcd目录,执行deployEtcd.yaml,完成ETCD集群的部署:
代码语言:javascript复制
[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服务
  1. 生成kube-apiserver所需的证书和私钥: 下面的命令生成kubernetes.pem和kubernetes-key.pem,需要把这两个文件拷贝到所有Master主机的/etc/kubernetes/pki目录里:
代码语言:javascript复制
[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
  1. 进入k8sdeploy/binary/deployApiServer目录执行部署脚本:
代码语言:javascript复制
[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主机上。

  1. 拷贝kubectl命令,并创建配置文件所需的目录:
代码语言:javascript复制
[root@km01 ~]# cp -a /tmp/kubernetes/server/bin/kubectl /usr/local/bin/
[root@km01 ~]# mkdir ~/.kube
  1. 创建证书和私钥:
代码语言:javascript复制
[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
  1. 创建kubeconfig配置文件: kubeconfig 为 kubectl 的配置文件,包含访问 kube-apiserver 所需的信息,如 kube-apiserver 地址、CA 证书和自身使用的证书:
代码语言:javascript复制
# 设置集群参数,--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
  1. 赋权,授予 kubernetes 证书访问 kubelet API 的权限: 在执行kubectl exec、run、logs等命令时,kube-apiserver会将请求转发到kubelet。这里定义 RBAC 规则,授权kube-apiserver 调用kubelet API:
代码语言:javascript复制
[root@km01 kubectl]# kubectl create clusterrolebinding kube-apiserver:kubelet-apis 
    --clusterrole=system:kubelet-api-admin --user kubernetes
  1. 验证:
代码语言:javascript复制
# 查看集群信息
[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服务
  1. 生成kube-controller-manager所需的证书及私钥:
代码语言:javascript复制
[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文件中。

  1. 创建kube-controller-manager的配置文件kubeconfig
代码语言:javascript复制
# 创建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文件中。

  1. 进入k8sdeploy/binary/deployControllerManager执行部署脚本:
代码语言:javascript复制
[root@km01 deployControllerManager]# ansible-playbook deployControllerManager.yaml
3.6.8 部署Kube-scheduler服务
  1. 创建证书和私钥:
代码语言:javascript复制
[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
  1. 创建scheduler的kubeconfig文件:
代码语言:javascript复制
[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文件中。

  1. 进入k8sdeploy/binary/deployScheduler执行部署脚本:
代码语言:javascript复制
[root@km01 deployScheduler]# ansible-playbook deployScheduler.yaml
3.6.9 部署Kubelet服务
  1. 创建bootstrap配置文件
代码语言:javascript复制
# 创建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目录中。

  1. 为bootstrap赋权
代码语言:javascript复制
[root@km01 kubectl]# kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --group=system:bootstrappers
  1. 进入k8sdeploy/binary/deployKubelet目录执行部署脚本:
代码语言:javascript复制
[root@km01 deployKubelet]# ansible-playbook deployKubelet.yaml
  1. Approve bootstrap请求:
代码语言:javascript复制
[root@km01 ~]# kubectl get csr
[root@km01 ~]# kubectl certificate approve <name>
3.6.10 部署Kube-proxy服务
  1. 创建证书和私钥:
代码语言:javascript复制
[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
  1. 创建kube-proxy的kubeconfig文件
代码语言:javascript复制
# 创建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
  1. 进入k8sdeploy/binary/deployKubeProxy目录执行部署脚本:
代码语言:javascript复制
[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
  1. IP测试
代码语言:javascript复制
# 测试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
  1. 域名测试

使用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集群中部署程序,以及生产中的常用操作。

文章转载自魏文弟。

0 人点赞