首页
学习
活动
专区
圈层
工具
发布
50 篇文章
1
kubernetes与velero的第一次尝试
2
在Kubernetes中如何针对Namespace进行资源限制?
3
kubernetes之metrics-server安装与配置
4
kubernetes部署metrics-server
5
Kubernetes1.20.9摘掉一个master节点再重新加入(ETCD需要注意的)
6
Kubernetes 1.17.17升级到1.18.20
7
Kubernetes 1.18.20升级到1.19.12
8
Kubernetes 1.19.12升级到1.20.9(强调一下selfLink)
9
Kubernetes 1.16.15升级到1.17.17
10
使用 kainstall 工具一键部署 kubernetes 高可用集群
11
附034.Kubernetes_v1.21.0高可用部署架构二
12
附016.Kubernetes_v1.17.4高可用部署
13
附022.Kubernetes_v1.18.3高可用部署架构一
14
附024.Kubernetes_v1.18.3高可用部署架构二
15
使用 StatefulSet 部署 etcd 集群
16
Kubernetes 稳定性保障手册 -- 极简版
17
Linux(centos7)离现安装kubernetes1.19.2和docker——组件部分
18
docker register 私有仓库部署 - http模式
19
KubeSphere 开源 KubeEye:Kubernetes 集群自动巡检工具
20
K8S 中的 CPUThrottlingHigh 到底是个什么鬼?
21
全链路分布式跟踪系统 Apache SkyWalking 入门教程
22
pod Evicted的状态究竟是何人所为
23
使用 ezctl 工具部署和管理 Kubernetes 集群
24
Kubernetes部署策略详解
25
kubernetes容器探针检测
26
使用Spring Boot实现动态健康检查HealthChecks
27
真一文搞定 ingress-nginx 的使用
28
K8S备份、恢复、迁移神器 Velero
29
一次关于k8s kubectl top 和 contained ps 不一致的问题探究
30
kubernetes备份恢复之velero
31
使用 Velero 进行集群备份与迁移
32
TKE集群中nginx-ingress使用实践
33
使用velero进行kubernetes灾备
34
Kubernetes 映射外部服务
35
运维体系建设套路
36
k8s解决pod调度不均衡的问题
37
ingress中虚拟路径解决方案
38
容器下的两地三中心建设
39
k8s集群外的主机访问pod的解决方案
40
k8s基础-健康检查机制
41
k8s基础-标签使用
42
ingress-nginx请求改写
43
nginx ingress server alias 多域名多证书问题
44
JAVA | Java 解决跨域问题 花式解决跨域问题
45
如何通过ingress-nginx实现应用灰度发布?
46
在Kubernetes(k8s)中使用GPU
47
使用 Prometheus-Operator 监控 Calico
48
使用Kubespray部署Kubernetes集群
49
云原生下的CI/CD:Argo CD 详解,手把手教你入门
50
Pod的健康检查机制
清单首页k8s文章详情

附034.Kubernetes_v1.21.0高可用部署架构二

kubeadm介绍

kubeadm概述

Kubeadm 是一个工具,它提供了 kubeadm init 以及 kubeadm join 这两个命令作为快速创建 kubernetes 集群的最佳实践。

kubeadm 通过执行必要的操作来启动和运行一个最小可用的集群。kubeadm 只关心启动集群,而不关心其他工作,如部署前的节点准备工作、安装各种Kubernetes Dashboard、监控解决方案以及特定云提供商的插件,这些都不属于 kubeadm 关注范围。

kubeadm功能

kubeadm 主要有如下功能:

  • kubeadm init 启动一个 Kubernetes 主节点;
  • kubeadm join 启动一个 Kubernetes 工作节点并且将其加入到集群;
  • kubeadm upgrade 更新一个 Kubernetes 集群到新版本;
  • kubeadm config 如果使用 v1.7.x 或者更低版本的 kubeadm 初始化集群,您需要对集群做一些配置以便使用 kubeadm upgrade 命令;
  • kubeadm token 管理 kubeadm join 使用的令牌;
  • kubeadm reset 还原 kubeadm init 或者 kubeadm join 对主机所做的任何更改;
  • kubeadm version 打印 kubeadm 版本;
  • kubeadm alpha 预览一组可用的新功能以便从社区搜集反馈。

本方案描述

本方案基于kubeadm部署,且实现高可用,同时提供相关Kubernetes周边组件。本方案可直接应用于生产环境。

  • 本方案采用kubeadm部署Kubernetes 1.21.0版本;
  • 基础系统为CentOS8.3;
  • etcd采用混部方式;
  • KeepAlived:实现VIP高可用;
  • HAProxy:以系统systemd形式运行,提供反向代理至3个master 6443端口;
  • 其他主要部署组件包括:
    • Metrics:度量;
    • Dashboard:Kubernetes 图形UI界面;
    • Helm:Kubernetes Helm包管理工具;
    • Ingress:Kubernetes 服务暴露;
    • containerd:Kubernetes底层容器时;
    • Longhorn:Kubernetes 动态存储组件。
  • worker04节点仅为测试模拟使用。

提示:本方案部署所使用脚本均由本人提供,可能不定期更新。

部署规划

节点规划

节点主机名

IP

类型

运行服务

master01

172.24.8.141

Kubernetes master节点

KeepAlived、HAProxy、containerd、etcd、kube-apiserver、kube-scheduler、kube-controller-manager、kubectl、kubelet、metrics、calico、rook-osd

master02

172.24.8.142

Kubernetes master节点

KeepAlived、HAProxy、containerd、etcd、kube-apiserver、kube-scheduler、kube-controller-manager、kubectl、kubelet、metrics、calico、rook-osd

master03

172.24.8.143

Kubernetes master节点

KeepAlived、HAProxy、containerd、etcd、kube-apiserver、kube-scheduler、kube-controller-manager、kubectl、kubelet、metrics、calico、rook-osd

worker01

172.24.8.144

Kubernetes worker节点

containerd、kubelet、proxy、calico、rook-osd、ingress

worker02

172.24.8.145

Kubernetes worker节点

containerd、kubelet、proxy、calico、rook-osd、ingress

worker03

172.24.8.146

Kubernetes worker节点

containerd、kubelet、proxy、calico、rook-osd、ingress

worker04

172.24.8.147

Kubernetes worker节点

containerd、kubelet、proxy、calico、rook-osd、ingress

Kubernetes的高可用主要指的是控制平面的高可用,即指多套Master节点组件和Etcd组件,工作节点通过负载均衡连接到各Master。

Kubernetes高可用架构中etcd与Master节点组件混布方式特点:

  • 所需机器资源少
  • 部署简单,利于管理
  • 容易进行横向扩展
  • etcd复用Kubernetes的高可用
  • 风险大,一台master主机挂了,master和etcd就都少了一套,集群冗余度受到一定影响

提示:本实验使用Keepalived+HAProxy架构实现Kubernetes的高可用。

主机名配置

建议对所有节点主机名进行相应配置。

代码语言:javascript
复制
[root@master01 ~]# hostnamectl set-hostname master01	    #其他节点依次修改

[root@master01 ~]# cat >> /etc/hosts << EOF
172.24.8.141 master01
172.24.8.142 master02
172.24.8.143 master03
172.24.8.144 worker01
172.24.8.145 worker02
172.24.8.146 worker03
EOF

变量准备

为实现自动化部署,便于管理和维护,建议做如下变量准备。

代码语言:javascript
复制
[root@master01 ~]# wget http://down.linuxsb.com/mydeploy/k8s/v1.21.0/environment.sh

[root@master01 ~]# vi environment.sh            #确认相关主机名和IP
#!/bin/sh
#****************************************************************#
# ScriptName: environment.sh
# Author: xhy
# Create Date: 2020-05-30 16:30
# Modify Author: xhy
# Modify Date: 2020-05-30 16:30
# Version: 
#***************************************************************#
# 集群 MASTER 机器 IP 数组
export MASTER_IPS=(172.24.8.141 172.24.8.142 172.24.8.143)

# 集群 MASTER IP 对应的主机名数组
export MASTER_NAMES=(master01 master02 master03)

# 集群 NODE 机器 IP 数组
export NODE_IPS=(172.24.8.144 172.24.8.145 172.24.8.146)

# 集群 NODE IP 对应的主机名数组
export NODE_NAMES=(worker01 worker02 worker03)

# 集群所有机器 IP 数组
export ALL_IPS=(172.24.8.141 172.24.8.142 172.24.8.143 172.24.8.144 172.24.8.145 172.24.8.146)

# 集群所有IP 对应的主机名数组
export ALL_NAMES=(master01 master02 master03 worker01 worker02 worker03)

互信配置

为了方便远程分发文件和执行命令,本实验配置master01节点到其它节点的 ssh 信任关系,即免秘钥管理所有其他节点。

代码语言:javascript
复制
[root@master01 ~]# ssh-keygen -f ~/.ssh/id_rsa -N ''
[root@master01 ~]# for all_ip in ${ALL_IPS[@]}
  do
    echo ">>> ${all_ip}"
    ssh-copy-id -i ~/.ssh/id_rsa.pub root@${all_ip}
  done

提示:此操作仅需要在master01节点操作。

环境初始化

kubeadm本身不负责对环境的准别,环境的初始化准备本方案使用脚本自动完成。

使用如下脚本对基础环境进行初始化,主要包括:

  • 安装containerd
  • 关闭SELinux及防火墙
  • 优化相关内核参数
  • 关闭swap
  • 设置相关模块
  • 配置相关基础软件
代码语言:javascript
复制
[root@master01 ~]# wget http://down.linuxsb.com/mydeploy/k8s/v1.21.0/k8sconinit.sh

[root@master01 ~]# vim k8sconinit.sh
#!/bin/sh
#****************************************************************#
# ScriptName: k8sinit.sh
# Author: xhy
# Create Date: 2020-05-30 16:30
# Modify Author: xhy
# Modify Date: 2021-04-16 07:35
# Version: 
#***************************************************************#
# Initialize the machine. This needs to be executed on every machine.
rm -f /var/lib/rpm/__db.00*
rpm -vv --rebuilddb
yum clean all 
yum makecache
sleep 3s
# Install containerd
CONVERSION=1.4.4                #确认containerd版本,其他保持默认
……                                                              

提示:此操作仅需要在master01节点操作。

  • 对于某些特性,可能需要升级内核,内核升级操作见018.Linux升级内核
  • 4.19版及以上内核nf_conntrack_ipv4已经改为nf_conntrack。
  • Kubernetes 1.20.0后可兼容的containerd版本最新为1.4.4。
代码语言:javascript
复制
[root@master01 ~]# source environment.sh
[root@master01 ~]# chmod +x *.sh
[root@master01 ~]# for all_ip in ${ALL_IPS[@]}
  do
    echo ">>> ${all_ip}"
    scp -rp /etc/hosts root@${all_ip}:/etc/hosts
    scp -rp k8sconinit.sh root@${all_ip}:/root/
    ssh root@${all_ip} "bash /root/k8sconinit.sh"
  done

部署高可用组件

HAProxy安装

HAProxy是可提供高可用性、负载均衡以及基于TCP(从而可以反向代理kubeapiserver等应用)和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种高可用解决方案。

代码语言:javascript
复制
[root@master01 ~]# for master_ip in ${MASTER_IPS[@]}
  do
    echo ">>> ${master_ip}"
    ssh root@${master_ip} "yum -y install gcc gcc-c++ make libnl3 libnl3-devel libnfnetlink openssl-devel wget openssh-clients systemd-devel zlib-devel pcre-devel"
    ssh root@${master_ip} "wget http://down.linuxsb.com/software/haproxy-2.3.9.tar.gz"
    ssh root@${master_ip} "tar -zxvf haproxy-2.3.9.tar.gz"
    ssh root@${master_ip} "cd haproxy-2.3.9/ && make ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_ZLIB=1 USE_SYSTEMD=1 PREFIX=/usr/local/haprpxy && make install PREFIX=/usr/local/haproxy"
    ssh root@${master_ip} "cp /usr/local/haproxy/sbin/haproxy /usr/sbin/"
    ssh root@${master_ip} "useradd -r haproxy && usermod -G haproxy haproxy"
    ssh root@${master_ip} "mkdir -p /etc/haproxy && cp -r /root/haproxy-2.3.9/examples/errorfiles/ /usr/local/haproxy/"
  done

KeepAlived安装

KeepAlived 是一个基于VRRP协议来实现的LVS服务高可用方案,可以解决静态路由出现的单点故障问题。本方案3台master节点运行Keepalived,一台为主服务器(MASTER),另外两台为备份服务器(BACKUP)。

对集群外表现为一个虚拟IP,主服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候,备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性。

代码语言:javascript
复制
[root@master01 ~]# for master_ip in ${MASTER_IPS[@]}
  do
    echo ">>> ${master_ip}"
    ssh root@${master_ip} "yum -y install curl gcc gcc-c++ make libnl3 libnl3-devel libnfnetlink openssl-devel"
    ssh root@${master_ip} "wget http://down.linuxsb.com/software/keepalived-2.2.2.tar.gz"
    ssh root@${master_ip} "tar -zxvf keepalived-2.2.2.tar.gz"
    ssh root@${master_ip} "cd keepalived-2.2.2/ && LDFLAGS=\"$LDFAGS -L /usr/local/openssl/lib/\" ./configure --sysconf=/etc --prefix=/usr/local/keepalived && make && make install"
    ssh root@${master_ip} "systemctl enable keepalived --now && systemctl restart keepalived"
  done

提示:如上仅需Master01节点操作,从而实现所有节点自动化安装。若出现如下报错:undefined reference to `OPENSSL_init_ssl’,可带上openssl lib路径:

LDFLAGS="$LDFAGS -L /usr/local/openssl/lib/" ./configure --sysconf=/etc --prefix=/usr/local/keepalived

创建配置文件

对集群相关的组件提前配置,可使用如下脚本定义。

代码语言:javascript
复制
[root@master01 ~]# wget http://down.linuxsb.com/mydeploy/k8s/v1.21.0/k8sconfig.sh				#拉取自动部署脚本

[root@master01 ~]# vi k8sconfig.sh
#!/bin/sh
#****************************************************************#
# ScriptName: k8sconfig
# Author: xhy
# Create Date: 2020-06-08 20:00
# Modify Author: xhy
# Modify Date: 2021-04-16 23:16
# Version: v3
#***************************************************************#
# set variables below to create the config files, all files will create at ./kubeadm directory

# master keepalived virtual ip address
export K8SHA_VIP=172.24.8.100

# master01 ip address
export K8SHA_IP1=172.24.8.141

# master02 ip address
export K8SHA_IP2=172.24.8.142

# master03 ip address
export K8SHA_IP3=172.24.8.143

# master01 hostname
export K8SHA_HOST1=master01

# master02 hostname
export K8SHA_HOST2=master02

# master03 hostname
export K8SHA_HOST3=master03

# master01 network interface name
export K8SHA_NETINF1=eth0

# master02 network interface name
export K8SHA_NETINF2=eth0

# master03 network interface name
export K8SHA_NETINF3=eth0

# keepalived auth_pass config
export K8SHA_KEEPALIVED_AUTH=412f7dc3bfed32194d1600c483e10ad1d

# kubernetes CIDR pod subnet
export K8SHA_PODCIDR=10.10.0.0

# kubernetes CIDR svc subnet
export K8SHA_SVCCIDR=10.20.0.0

[root@master01 ~]# bash k8sconfig.sh

解释:如上仅需Master01节点操作。执行k8sconfig.sh脚本后会生产如下配置文件清单:

  • kubeadm-config.yaml:kubeadm初始化配置文件,位于kubeadm/目录
  • keepalived:keepalived配置文件,位于各个master节点的/etc/keepalived目录
  • haproxy:haproxy的配置文件,位于各个master节点的/etc/haproxy/目录
  • calico.yaml:calico网络组件部署文件,位于kubeadm/calico/目录
代码语言:javascript
复制
[root@master01 ~]# vim kubeadm/kubeadm-config.yaml	#检查集群初始化配置
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
networking:
  serviceSubnet: "10.20.0.0/16"			     	    #设置svc网段
  podSubnet: "10.10.0.0/16"                         #设置Pod网段
  dnsDomain: "cluster.local"
kubernetesVersion: "v1.21.0"			    	    #设置安装版本
controlPlaneEndpoint: "172.24.8.100:16443"		    #设置相关API VIP地址
apiServer:
  certSANs:
  - master01
  - master02
  - master03
  - 127.0.0.1
  - 172.24.8.141
  - 172.24.8.142
  - 172.24.8.143
  - 172.24.8.100
  timeoutForControlPlane: 4m0s
certificatesDir: "/etc/kubernetes/pki"
imageRepository: "k8s.gcr.io"

---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs

提示:如上仅需Master01节点操作,更多config文件参考:https://pkg.go.dev/k8s.io/kubernetes@v1.21.0/cmd/kubeadm/app/apis/kubeadm/v1beta2。

此kubeadm部署初始化配置更多参考:https://pkg.go.dev/k8s.io/kubernetes@v1.21.0/cmd/kubeadm/app/apis/kubeadm/v1beta2。

默认kubeadm配置可使用kubeadm config print init-defaults > config.yaml生成。

启动服务

提前启动KeepAlive和HAProxy,提前准备好高可用环境。

代码语言:javascript
复制
[root@master01 ~]# cat /etc/keepalived/keepalived.conf
[root@master01 ~]# cat /etc/keepalived/check_apiserver.sh	#确认Keepalived配置

[root@master01 ~]# for master_ip in ${MASTER_IPS[@]}
  do
    echo ">>> ${master_ip}"
    ssh root@${master_ip} "systemctl enable haproxy.service --now && systemctl restart haproxy.service"
    ssh root@${master_ip} "systemctl enable keepalived.service --now && systemctl restart keepalived.service"
    ssh root@${master_ip} "systemctl status keepalived.service | grep Active"
    ssh root@${master_ip} "systemctl status haproxy.service | grep Active"
  done

[root@master01 ~]# for all_ip in ${ALL_IPS[@]}
  do
    echo ">>> ${all_ip}"
    ssh root@${all_ip} "ping -c1 172.24.8.100"
  done								#等待10s执行检查

提示:如上仅需Master01节点操作,从而实现所有节点自动启动服务。

集群部署

相关组件包

需要在每台机器上都安装以下的软件包:

  • kubeadm: 用来初始化集群的指令;
  • kubelet: 在集群中的每个节点上用来启动 pod 和 container 等;
  • kubectl: 用来与集群通信的命令行工具。

kubeadm不能安装或管理 kubelet 或 kubectl ,所以得保证他们满足通过 kubeadm 安装的 Kubernetes控制层对版本的要求。如果版本没有满足要求,可能导致一些意外错误或问题。

具体相关组件安装见;附001.kubectl介绍及使用书

提示:Kubernetes 1.21.0版本所有兼容相应组件的版本参考:https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.21.md。

正式安装

代码语言:javascript
复制
[root@master01 ~]# for all_ip in ${ALL_IPS[@]}
  do
    echo ">>> ${all_ip}"
    ssh root@${all_ip} "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"
    ssh root@${all_ip} "yum install -y kubeadm-1.21.0-0.x86_64 kubelet-1.21.0-0.x86_64 kubectl-1.21.0-0.x86_64 --disableexcludes=kubernetes"
    ssh root@${all_ip} "systemctl enable kubelet"
done

[root@master01 ~]# yum search -y kubelet --showduplicates             #查看相应版本 

提示:如上仅需Master01节点操作,从而实现所有节点自动化安装,同时此时不需要启动kubelet,初始化的过程中会自动启动的,如果此时启动了会出现报错,忽略即可。

说明:同时安装了cri-tools, kubernetes-cni, socat三个依赖:

socat:kubelet的依赖;

cri-tools:即CRI(Container Runtime Interface)容器运行时接口的命令行工具。

集群初始化

拉取镜像

初始化过程中会pull大量镜像,并且镜像位于国外,可能出现无法pull的情况导致Kubernetes初始化失败。建议提前准备镜像,保证后续初始化。

代码语言:javascript
复制
[root@master01 ~]# kubeadm --kubernetes-version=v1.21.0 config images list     	#列出所需镜像

[root@master01 ~]# cat <<EOF > kubeadm/conloadimage.sh
#!/bin/sh
#****************************************************************#
# ScriptName: conloadimage.sh
# Author: xhy
# Create Date: 2021-04-15 14:03
# Modify Author: xhy
# Modify Date: 2021-04-15 17:35
# Version: 
#***************************************************************#

KUBE_VERSION=v1.21.0
CALICO_VERSION=v3.18.1
CALICO_URL='docker.io/calico'
KUBE_PAUSE_VERSION=3.4.1
ETCD_VERSION=3.4.13-0
CORE_DNS_VERSION=v1.8.0
GCR_URL=k8s.gcr.io
METRICS_SERVER_VERSION=v0.4.2
INGRESS_VERSION=v0.45.0
CSI_PROVISIONER_VERSION=v1.6.0-lh1
CSI_NODE_DRIVER_VERSION=v1.2.0-lh1
CSI_ATTACHER_VERSION=v2.2.1-lh1
CSI_RESIZER_VERSION=v0.5.1-lh1
DEFAULTBACKENDVERSION=1.5
ALIYUN_URL=registry.cn-hangzhou.aliyuncs.com/google_containers
UCLOUD_URL=uhub.service.ucloud.cn/uxhy
QUAY_URL=quay.io

mkdir -p conimages/

# config node hostname
export ALL_NAMES=(master02 master03 worker01 worker02 worker03)

kubeimages=(kube-proxy:\${KUBE_VERSION}
kube-scheduler:\${KUBE_VERSION}
kube-controller-manager:\${KUBE_VERSION}
kube-apiserver:\${KUBE_VERSION}
pause:\${KUBE_PAUSE_VERSION}
etcd:\${ETCD_VERSION}
)

corednsimages=(coredns:\${CORE_DNS_VERSION}
)

for corednsimageName in \${corednsimages[@]} ; do
echo \${corednsimageName}
ctr -n k8s.io images pull \${UCLOUD_URL}/\${corednsimageName}
ctr -n k8s.io images tag \${UCLOUD_URL}/\${corednsimageName} \${GCR_URL}/coredns/\${corednsimageName}
ctr -n k8s.io images rm \${UCLOUD_URL}/\${corednsimageName}
ctr -n k8s.io images export conimages/\${corednsimageName}\.tar \${GCR_URL}/coredns/\${corednsimageName}
done

for kubeimageName in \${kubeimages[@]} ; do
echo \${kubeimageName}
ctr -n k8s.io images pull \${UCLOUD_URL}/\${kubeimageName}
ctr -n k8s.io images tag \${UCLOUD_URL}/\${kubeimageName} \${GCR_URL}/\${kubeimageName}
ctr -n k8s.io images rm \${UCLOUD_URL}/\${kubeimageName}
ctr -n k8s.io images export conimages/\${kubeimageName}\.tar \${GCR_URL}/\${kubeimageName}
done

metricsimages=(metrics-server:\${METRICS_SERVER_VERSION})

for metricsimageName in \${metricsimages[@]} ; do
echo \${metricsimageName}
ctr -n k8s.io images pull \${UCLOUD_URL}/\${metricsimageName}
ctr -n k8s.io images tag \${UCLOUD_URL}/\${metricsimageName} \${GCR_URL}/metrics-server/\${metricsimageName}
ctr -n k8s.io images rm \${UCLOUD_URL}/\${metricsimageName}
ctr -n k8s.io images export conimages/\${metricsimageName}\.tar \${GCR_URL}/metrics-server/\${metricsimageName}
done

calimages=(cni:\${CALICO_VERSION}
pod2daemon-flexvol:\${CALICO_VERSION}
node:\${CALICO_VERSION}
kube-controllers:\${CALICO_VERSION})

for calimageName in \${calimages[@]} ; do
echo \${calimageName}
ctr -n k8s.io images pull \${UCLOUD_URL}/\${calimageName}
ctr -n k8s.io images tag \${UCLOUD_URL}/\${calimageName} \${CALICO_URL}/\${calimageName}
ctr -n k8s.io images rm \${UCLOUD_URL}/\${calimageName}
ctr -n k8s.io images export conimages/\${calimageName}\.tar \${CALICO_URL}/\${calimageName}
done

ingressimages=(controller:\${INGRESS_VERSION})

for ingressimageName in \${ingressimages[@]} ; do
echo \${ingressimageName}
ctr -n k8s.io images pull \${UCLOUD_URL}/\${ingressimageName}
ctr -n k8s.io images tag \${UCLOUD_URL}/\${ingressimageName} \${GCR_URL}/ingress-nginx/\${ingressimageName}
ctr -n k8s.io images rm \${UCLOUD_URL}/\${ingressimageName}
ctr -n k8s.io images export conimages/\${ingressimageName}\.tar \${GCR_URL}/ingress-nginx/\${ingressimageName}
done

csiimages=(csi-provisioner:\${CSI_PROVISIONER_VERSION}
csi-node-driver-registrar:\${CSI_NODE_DRIVER_VERSION}
csi-attacher:\${CSI_ATTACHER_VERSION}
csi-resizer:\${CSI_RESIZER_VERSION}
)

for csiimageName in \${csiimages[@]} ; do
echo \${csiimageName}
ctr -n k8s.io images pull \${UCLOUD_URL}/\${csiimageName}
ctr -n k8s.io images tag \${UCLOUD_URL}/\${csiimageName} longhornio/\${csiimageName}
ctr -n k8s.io images rm \${UCLOUD_URL}/\${csiimageName}
ctr -n k8s.io images export conimages/\${csiimageName}\.tar longhornio/\${csiimageName}
done

otherimages=(defaultbackend-amd64:\${DEFAULTBACKENDVERSION})

for otherimagesName in \${otherimages[@]} ; do
echo \${otherimagesName}
ctr -n k8s.io images pull \${UCLOUD_URL}/\${otherimagesName}
ctr -n k8s.io images tag \${UCLOUD_URL}/\${otherimagesName} \${GCR_URL}/\${otherimagesName}
ctr -n k8s.io images rm \${UCLOUD_URL}/\${otherimagesName}
ctr -n k8s.io images export conimages/\${otherimagesName}\.tar \${GCR_URL}/\${otherimagesName}
done

allimages=(kube-proxy:\${KUBE_VERSION}
kube-scheduler:\${KUBE_VERSION}
kube-controller-manager:\${KUBE_VERSION}
kube-apiserver:\${KUBE_VERSION}
pause:\${KUBE_PAUSE_VERSION}
etcd:\${ETCD_VERSION}
coredns:\${CORE_DNS_VERSION}
metrics-server:\${METRICS_SERVER_VERSION}
cni:\${CALICO_VERSION}
pod2daemon-flexvol:\${CALICO_VERSION}
node:\${CALICO_VERSION}
kube-controllers:\${CALICO_VERSION}
controller:\${INGRESS_VERSION}
csi-provisioner:\${CSI_PROVISIONER_VERSION}
csi-node-driver-registrar:\${CSI_NODE_DRIVER_VERSION}
csi-attacher:\${CSI_ATTACHER_VERSION}
csi-resizer:\${CSI_RESIZER_VERSION}
defaultbackend-amd64:\${DEFAULTBACKENDVERSION}
)

for all_name in \${ALL_NAMES[@]}
  do  
    echo ">>> \${all_name}"
    ssh root@\${all_name} "mkdir /root/conimages"
    scp -rp conimages/* root@\${all_name}:/root/conimages/
  done

for allimageName in \${allimages[@]}
  do
  for all_name in \${ALL_NAMES[@]}
    do
    echo "\${allimageName} copy to \${all_name}"
    ssh root@\${all_name} "ctr -n k8s.io images import conimages/\${allimageName}\.tar"
    done
  done
EOF

#确认版本,提前下载镜像
[root@master01 ~]# bash kubeadm/conloadimage.sh

提示:如上仅需Master01节点操作,从而实现所有节点镜像的分发。

注意相关版本,如上脚本为v1.21.0 Kubernetes版本所需镜像。

代码语言:javascript
复制
[root@master01 ~]# ctr -n k8s.io images ls        	#确认验证
[root@master01 ~]# crictl images ls

Master01上初始化

代码语言:javascript
复制
[root@master01 ~]# kubeadm init --config=kubeadm/kubeadm-config.yaml --upload-certs                 #保留如下命令用于后续节点添加:
You can now join any number of the control-plane node running the following command on each as root:

  kubeadm join 172.24.8.100:16443 --token 6h8ncy.g0lzrgiav8ct7kyo \
        --discovery-token-ca-cert-hash sha256:41c1966aa5aaf6108b938daf3bdcf103991be5fd8141854f800a4bbc3df7979a \
        --control-plane --certificate-key f32602ab63d2545b8cab5d392d0e53942872fac8cfc23c8ae1ee545f4e365394

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 172.24.8.100:16443 --token 6h8ncy.g0lzrgiav8ct7kyo \
        --discovery-token-ca-cert-hash sha256:41c1966aa5aaf6108b938daf3bdcf103991be5fd8141854f800a4bbc3df7979a

注意:如上token具有默认24小时的有效期,token和hash值可通过如下方式获取:

kubeadm token list

如果 Token 过期以后,可以输入以下命令,生成新的 Token:

代码语言:javascript
复制
kubeadm token create
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
代码语言:javascript
复制
[root@master01 ~]# mkdir -p $HOME/.kube
[root@master01 ~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@master01 ~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config

[root@master01 ~]# cat << EOF >> ~/.bashrc
export KUBECONFIG=$HOME/.kube/config
EOF							#设置KUBECONFIG环境变量

[root@master01 ~]# echo "source <(kubectl completion bash)" >> ~/.bashrc
[root@master01 ~]# source ~/.bashrc

附加:初始化过程大致步骤如下:

  • certs:生成相关的各种证书
  • control-plane:创建Kubernetes控制节点的静态Pod
  • etcd:创建ETCD的静态Pod
  • kubelet-start:生成kubelet的配置文件”/var/lib/kubelet/config.yaml”
  • kubeconfig:生成相关的kubeconfig文件
  • bootstraptoken:生成token记录下来,后续使用kubeadm join往集群中添加节点时会用到
  • addons:附带的相关插件

提示:初始化仅需要在master01上执行,若初始化异常可通过kubeadm reset && rm -rf $HOME/.kube重置。

添加Master节点

代码语言:javascript
复制
[root@master02 ~]# kubeadm join 172.24.8.100:16443 --token 6h8ncy.g0lzrgiav8ct7kyo \
        --discovery-token-ca-cert-hash sha256:41c1966aa5aaf6108b938daf3bdcf103991be5fd8141854f800a4bbc3df7979a \
        --control-plane --certificate-key f32602ab63d2545b8cab5d392d0e53942872fac8cfc23c8ae1ee545f4e365394
代码语言:javascript
复制
[root@master02 ~]# mkdir -p $HOME/.kube
[root@master02 ~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@master02 ~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config
[root@master02 ~]# cat << EOF >> ~/.bashrc
export KUBECONFIG=$HOME/.kube/config
EOF						               	#设置KUBECONFIG环境变量
[root@master02 ~]# echo "source <(kubectl completion bash)" >> ~/.bashrc
[root@master02 ~]# source ~/.bashrc

提示:master03也如上执行添加至集群的controlplane。

若添加异常可通过kubeadm reset && rm -rf $HOME/.kube重置。

安装NIC插件

NIC插件介绍

  • Calico 是一个安全的 L3 网络和网络策略提供者。
  • Canal 结合 Flannel 和 Calico, 提供网络和网络策略。
  • Cilium 是一个 L3 网络和网络策略插件, 能够透明的实施 HTTP/API/L7 策略。 同时支持路由(routing)和叠加/封装( overlay/encapsulation)模式。
  • Contiv 为多种用例提供可配置网络(使用 BGP 的原生 L3,使用 vxlan 的 overlay,经典 L2 和 Cisco-SDN/ACI)和丰富的策略框架。Contiv 项目完全开源。安装工具同时提供基于和不基于 kubeadm 的安装选项。
  • Flannel 是一个可以用于 Kubernetes 的 overlay 网络提供者。 +Romana 是一个 pod 网络的层 3 解决方案,并且支持 NetworkPolicy API。Kubeadm add-on 安装细节可以在这里找到。
  • Weave Net 提供了在网络分组两端参与工作的网络和网络策略,并且不需要额外的数据库。
  • CNI-Genie 使 Kubernetes 无缝连接到一种 CNI 插件,例如:Flannel、Calico、Canal、Romana 或者 Weave。

提示:本方案使用Calico插件。

部署calico

确认相关配置,如MTU,网卡接口,Pod的IP地址段。

代码语言:javascript
复制
[root@master01 ~]# cat kubeadm/calico/calico.yaml | grep -A1 -E 'CALICO_IPV4POOL_CIDR|IP_AUTODETECTION_METHOD|veth_mtu:'	#检查配置
……
  veth_mtu: "1400"                                                  #calico建议为主机MTU减去50,

--
            - name: IP_AUTODETECTION_METHOD
              value: "interface=eth.*"		     	                #检查节点之间的网卡
--
            - name: CALICO_IPV4POOL_CIDR
              value: "10.10.0.0/16"		         	                #检查Pod网段

……

[root@master01 ~]# kubectl apply -f kubeadm/calico/calico.yaml
[root@master01 ~]# kubectl get pods --all-namespaces -o wide		#查看部署
[root@master01 ~]# kubectl get nodes

提示:官方calico参考:https://docs.projectcalico.org/manifests/calico.yaml。

修改node端口范围

默认Kubernetes的端口范围为30000-32767,为便于后期应用,如ingress的80、443端口,建议开放全端口。同时开放全端口范围后,需要注意避开公共端口,如8080。

代码语言:javascript
复制
[root@master01 ~]# vi /etc/kubernetes/manifests/kube-apiserver.yaml
……
    - --service-node-port-range=1-65535
……

提示:如上需要在所有Master节点操作。

开启非安全端口

kube-scheduler和kube-controller-manager的健康检查使用非安全端口,因此建议打开。

代码语言:javascript
复制
root@master01:~# vi /etc/kubernetes/manifests/kube-scheduler.yaml
……
#     - --port=0						#删掉或注释关闭非安全端口的配置,从而打开非安全端口
……
root@master01:~# vi /etc/kubernetes/manifests/kube-controller-manager.yaml
……
#     - --port=0					    #删掉或注释关闭非安全端口的配置,从而打开非安全端口
……

提示:如上需在所有Master节点操作。

添加Worker节点

添加Worker节点

代码语言:javascript
复制
[root@master01 ~]# source environment.sh

[root@master01 ~]# for node_ip in ${NODE_IPS[@]}
  do
    echo ">>> ${node_ip}"
    ssh root@${node_ip} "kubeadm join 172.24.8.100:16443 --token 6h8ncy.g0lzrgiav8ct7kyo \
        --discovery-token-ca-cert-hash sha256:41c1966aa5aaf6108b938daf3bdcf103991be5fd8141854f800a4bbc3df7979a"
    ssh root@${node_ip} "systemctl enable kubelet.service"
  done

提示:如上仅需Master01节点操作,从而实现所有Worker节点添加至集群,若添加异常可通过如下方式重置:

代码语言:javascript
复制
[root@worker01 ~]# kubeadm reset
[root@worker01 ~]# ifconfig cni0 down
[root@worker01 ~]# ip link delete cni0
[root@worker01 ~]# ifconfig flannel.1 down
[root@worker01 ~]# ip link delete flannel.1
[root@worker01 ~]# rm -rf /var/lib/cni/

确认验证

代码语言:javascript
复制
[root@master01 ~]# kubectl get nodes			         	#节点状态
[root@master01 ~]# kubectl get cs			             	#组件状态
[root@master01 ~]# kubectl get serviceaccount		     	#服务账户
[root@master01 ~]# kubectl cluster-info			         	#集群信息
[root@master01 ~]# kubectl get pod -n kube-system -o wide	#所有服务状态

提示:更多Kubetcl使用参考:https://kubernetes.io/docs/reference/kubectl/kubectl/

https://kubernetes.io/docs/reference/kubectl/overview/

更多kubeadm使用参考:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/

Metrics部署

Metrics介绍

Kubernetes的早期版本依靠Heapster来实现完整的性能数据采集和监控功能,Kubernetes从1.8版本开始,性能数据开始以Metrics API的方式提供标准化接口,并且从1.10版本开始将Heapster替换为Metrics Server。在Kubernetes新的监控体系中,Metrics Server用于提供核心指标(Core Metrics),包括Node、Pod的CPU和内存使用指标。

对其他自定义指标(Custom Metrics)的监控则由Prometheus等组件来完成。

开启聚合层

有关聚合层知识参考:https://blog.csdn.net/liukuan73/article/details/81352637

kubeadm方式部署默认已开启。

获取部署文件

代码语言:javascript
复制
[root@master01 ~]# mkdir metrics
[root@master01 ~]# cd metrics/
[root@master01 metrics]# wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
代码语言:javascript
复制
[root@master01 metrics]# vi components.yaml
……
apiVersion: apps/v1
kind: Deployment
……
spec:
  replicas: 3						        	#根据集群规模调整副本数
……
    spec:
      hostNetwork: true
      containers:
      - args:
        - --cert-dir=/tmp
        - --secure-port=4443
        - --kubelet-insecure-tls				#追加此args
        - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname,InternalDNS,ExternalDNS          #追加此args
        - --kubelet-use-node-status-port
        image: k8s.gcr.io/metrics-server/metrics-server:v0.4.2
        imagePullPolicy: IfNotPresent
……

正式部署

代码语言:javascript
复制
[root@master01 metrics]# kubectl apply -f components.yaml
[root@master01 metrics]# kubectl -n kube-system get pods -l k8s-app=metrics-server
NAME                              READY   STATUS    RESTARTS   AGE
metrics-server-7bc5984686-px9lr   1/1     Running   0          66s
metrics-server-7bc5984686-qffb2   1/1     Running   0          66s
metrics-server-7bc5984686-t89z5   1/1     Running   0          66s

查看资源监控

代码语言:javascript
复制
[root@master01 ~]# kubectl top nodes
[root@master01 ~]# kubectl top pods --all-namespaces

提示:Metrics Server提供的数据也可以供HPA控制器使用,以实现基于CPU使用率或内存使用值的Pod自动扩缩容功能。

部署参考:https://linux48.com/container/2019-11-13-metrics-server.html

有关metrics更多部署参考:

https://kubernetes.io/docs/tasks/debug-application-cluster/resource-metrics-pipeline/

开启开启API Aggregation参考:

https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/

API Aggregation介绍参考:

https://kubernetes.io/docs/tasks/access-kubernetes-api/configure-aggregation-layer/

Nginx ingress部署

通常Service的表现形式为IP:Port,即工作在TCP/IP层。

对于基于HTTP的服务来说,不同的URL地址经常对应到不同的后端服务(RS)或者虚拟服务器(Virtual Host),这些应用层的转发机制仅通过Kubernetes的Service机制是无法实现的。

从Kubernetes 1.1版本开始新增Ingress资源对象,用于将不同URL的访问请求转发到后端不同的Service,以实现HTTP层的业务路由机制。

Kubernetes使用了一个Ingress策略定义和一个具体的Ingress Controller,两者结合并实现了一个完整的Ingress负载均衡器。使用Ingress进行负载分发时,Ingress Controller基于Ingress规则将客户端请求直接转发到Service对应的后端Endpoint(Pod)上,从而跳过kube-proxy的转发功能,kube-proxy不再起作用。

简单的理解就是:ingress使用DaemonSet或Deployment在相应Node上监听80,然后配合相应规则,因为Nginx外面绑定了宿主机80端口(就像 NodePort),本身又在集群内,那么向后直接转发到相应ServiceIP即可实现相应需求。ingress controller + ingress 规则 ----> services。

同时当Ingress Controller提供的是对外服务,则实际上实现的是边缘路由器的功能。

典型的HTTP层路由的架构:

设置标签

代码语言:javascript
复制
[root@master01 ~]# kubectl label nodes master0{1,2,3} ingress=enable

提示:建议对于非上次业务相关的应用(如Ingress),部署在master节点,也能复用master节点的高可用。

获取资源

代码语言:javascript
复制
[root@master01 ~]# mkdir ingress
[root@master01 ~]# cd ingress/
[root@master01 ingress]# wget http://down.linuxsb.com/kubernetes/ingress-nginx/controller-v0.45.0/deploy/static/provider/baremetal/deploy.yaml

提示:ingress官方参考:https://github.com/kubernetes/ingress-nginx

https://kubernetes.github.io/ingress-nginx/deploy/

修改配置

为方便后续管理和排障,对相关Nginx ingress挂载时区,以便于使用主机时间。

同时对ingress做了简单配置,如日志格式等。

代码语言:javascript
复制
[root@master01 ingress]# vi deploy.yaml
……
apiVersion: apps/v1
kind: Deployment
#kind: DaemonSet
……
spec:
  replicas: 3
……
          image: k8s.gcr.io/ingress-nginx/controller:v0.45.0
……          
          volumeMounts:
……
            - name: timeconfig
              mountPath: /etc/localtime
              readOnly: true
              ……
      volumes:
……
        - name: timeconfig
          hostPath:
            path: /etc/localtime
      nodeSelector:
        ingress: enable
      tolerations:
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
……
apiVersion: v1
kind: ConfigMap
metadata:
……
data:
  # 客户端请求头的缓冲区大小
  client-header-buffer-size: "512k"
  # 设置用于读取大型客户端请求标头的最大值number和size缓冲区
  large-client-header-buffers: "4 512k"
  # 读取客户端请求body的缓冲区大小
  client-body-buffer-size: "128k"
  # 代理缓冲区大小
  proxy-buffer-size: "256k"
  # 代理body大小
  proxy-body-size: "50m"
  # 服务器名称哈希大小
  server-name-hash-bucket-size: "128"
  # map哈希大小
  map-hash-bucket-size: "128"
  # SSL加密套件
  ssl-ciphers: "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"
  # ssl 协议
  ssl-protocols: "TLSv1 TLSv1.1 TLSv1.2"
  # 日志格式
  log-format-upstream: '{"time": "$time_iso8601", "remote_addr": "$proxy_protocol_addr", "x-forward-for": "$proxy_add_x_forwarded_for", "request_id": "$req_id","remote_user": "$remote_user", "bytes_sent": $bytes_sent, "request_time": $request_time, "status":$status, "vhost": "$host", "request_proto": "$server_protocol", "path": "$uri", "request_query": "$args", "request_length": $request_length, "duration": $request_time,"method": "$request_method", "http_referrer": "$http_referer", "http_user_agent": "$http_user_agent" }'
……
apiVersion: v1
kind: Service
……
  name: ingress-nginx-controller
……  
spec:
  type: NodePort
  externalTrafficPolicy: Local          #追加
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: http
      nodePort: 80
    - name: https
      port: 443
      protocol: TCP
      targetPort: https
      nodePort: 443
……

[root@master01 ingress]# kubectl apply -f deploy.yaml

提示:添加默认backend需要等待default-backend创建完成controllers才能成功部署,新版本ingress不再推荐添加default backend。

确认验证

代码语言:javascript
复制
[root@master01 ingress]# kubectl get pods -n ingress-nginx -o wide
[root@master01 ingress]# kubectl get svc -n ingress-nginx -o wide

提示:参考文档:https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md。

Dashboard部署

dashboard是基于Web的Kubernetes用户界面。可以使用dashboard将容器化应用程序部署到Kubernetes集群,对容器化应用程序进行故障排除,以及管理集群资源。可以使用dashboard来概述群集上运行的应用程序,以及创建或修改单个Kubernetes资源(例如部署、任务、守护进程等)。

可以使用部署向导扩展部署,启动滚动更新,重新启动Pod或部署新应用程序。

dashboard还提供有关群集中Kubernetes资源状态以及可能发生的任何错误的信息。

设置标签

代码语言:javascript
复制
[root@master01 ~]# kubectl label nodes master0{1,2,3} dashboard=enable

提示:建议对于Kubernetes自身相关的应用(如dashboard),此类非业务应用部署在master节点。

创建证书

本实验已获取免费一年的证书,免费证书获取可参考:https://freessl.cn

代码语言:javascript
复制
[root@master01 ~]# mkdir -p /root/dashboard/certs
[root@master01 ~]# cd /root/dashboard/certs
[root@master01 certs]# mv web.odocker.com.crt tls.crt
[root@master01 certs]# mv web.odocker.com.key tls.key
[root@master01 certs]# ll
total 8.0K
-rw-r--r-- 1 root root 1.9K Jun  8 11:46 tls.crt
-rw-r--r-- 1 root root 1.7K Jun  8 11:46 tls.ke

提示:也可手动如下操作创建自签证书:

[root@master01 ~]# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=ZheJiang/L=HangZhou/O=Xianghy/OU=Xianghy/CN=web.odocker.com"

手动创建secret

代码语言:javascript
复制
[root@master01 ~]# kubectl create ns kubernetes-dashboard	                                        #v2版本dashboard独立ns
[root@master01 ~]# kubectl create secret generic kubernetes-dashboard-certs --from-file=/root/dashboard/certs/ -n kubernetes-dashboard
[root@master01 ~]# kubectl get secret kubernetes-dashboard-certs -n kubernetes-dashboard -o yaml	#查看新证书`

下载yaml

代码语言:javascript
复制
[root@master01 ~]# cd /root/dashboard
[root@master01 dashboard]# wget http://down.linuxsb.com/kubernetes/dashboard/v2.2.0/aio/deploy/recommended.yaml

提示:官方参考:https://github.com/kubernetes/dashboard。

修改yaml

代码语言:javascript
复制
[root@master01 dashboard]# vi recommended.yaml
……
kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  type: NodePort			                	#新增
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30001			            	#新增
  selector:
    k8s-app: kubernetes-dashboard
---
……						                        #如下全部注释
#apiVersion: v1
#kind: Secret
#metadata:
#  labels:
#    k8s-app: kubernetes-dashboard
#  name: kubernetes-dashboard-certs
#  namespace: kubernetes-dashboard
#type: Opaque
……
kind: Deployment
……
  replicas: 3					                #适当调整为3副本
……
    spec:
      containers:
        - name: kubernetes-dashboard
          image: kubernetesui/dashboard:v2.2.0
          imagePullPolicy: IfNotPresent         #修改镜像下载策略
          ports:
            - containerPort: 8443
              protocol: TCP
          args:
            - --auto-generate-certificates
            - --namespace=kubernetes-dashboard
            - --tls-key-file=tls.key
            - --tls-cert-file=tls.crt
            - --token-ttl=3600	       		    #追加如上args
……
      nodeSelector:
#        "kubernetes.io/os": "linux"
        "dashboard": enable	        		    #部署在master节点
……
kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: dashboard-metrics-scraper
  name: dashboard-metrics-scraper
  namespace: kubernetes-dashboard
spec:
  type: NodePort	             			    #新增
  ports:
    - port: 8000
      targetPort: 8000
      nodePort: 30000		         		    #新增
  selector:                                                                                  
    k8s-app: dashboard-metrics-scraper
……
   replicas: 3			            		    #适当调整为3副本
……
      nodeSelector:
#        "beta.kubernetes.io/os": linux
        "dashboard": enable	        		    #部署在master节点
……

正式部署

代码语言:javascript
复制
[root@master01 dashboard]# kubectl apply -f recommended.yaml
[root@master01 dashboard]# kubectl get deployment kubernetes-dashboard -n kubernetes-dashboard
[root@master01 dashboard]# kubectl get services -n kubernetes-dashboard
[root@master01 dashboard]# kubectl get pods -o wide -n kubernetes-dashboard

提示:master NodePort 30001/TCP映射到 dashboard pod 443 端口。

创建管理员账户

提示:dashboard v2版本默认没有创建具有管理员权限的账户,可如下操作创建。

代码语言:javascript
复制
[root@master01 dashboard]# cat <<EOF > dashboard-admin.yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin
  namespace: kubernetes-dashboard

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin
  namespace: kubernetes-dashboard
EOF

[root@master01 dashboard]# kubectl apply -f dashboard-admin.yaml

ingress暴露dashboard

创建ingress tls

代码语言:javascript
复制
[root@master01 dashboard]# kubectl -n kubernetes-dashboard create secret tls kubernetes-dashboard-tls --cert=/root/dashboard/certs/tls.crt --key=/root/dashboard/certs/tls.key
[root@master01 dashboard]# kubectl -n kubernetes-dashboard describe secrets kubernetes-dashboard-tls

创建ingress策略

代码语言:javascript
复制
[root@master01 dashboard]# cat <<EOF > dashboard-ingress.yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kubernetes-dashboard-ingress
  namespace: kubernetes-dashboard
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    #nginx.ingress.kubernetes.io/secure-backends: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_ssl_session_reuse off;
spec:
  rules:
  - host: web.odocker.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: kubernetes-dashboard
            port:
              number: 443
  tls:
  - hosts:
    - web.odocker.com
    secretName: kubernetes-dashboard-tls
EOF
代码语言:javascript
复制
[root@master01 dashboard]# kubectl apply -f dashboard-ingress.yaml
[root@master01 dashboard]# kubectl -n kubernetes-dashboard get ingress

访问dashboard

创建kubeconfig文件

使用token相对复杂,可将token添加至kubeconfig文件中,使用KubeConfig文件访问dashboard。

代码语言:javascript
复制
[root@master01 dashboard]# ADMIN_SECRET=$(kubectl -n kubernetes-dashboard get secret | grep admin | awk '{print $1}') 
[root@master01 dashboard]# DASHBOARD_LOGIN_TOKEN=$(kubectl describe secret -n kubernetes-dashboard ${ADMIN_SECRET} | grep -E '^token' | awk '{print $2}') 
[root@master01 dashboard]# kubectl config set-cluster kubernetes \
  --certificate-authority=/etc/kubernetes/pki/ca.crt \
  --embed-certs=true \
  --server=172.24.8.100:16443 \
  --kubeconfig=local-ngkeconk8s-1-21-admin.kubeconfig		# 设置集群参数
 [root@master01 dashboard]# kubectl config set-credentials dashboard_user \
  --token=${DASHBOARD_LOGIN_TOKEN} \
  --kubeconfig=local-ngkeconk8s-1-21-admin.kubeconfig       # 设置客户端认证参数,使用上面创建的 Token
[root@master01 dashboard]# kubectl config set-context default \
  --cluster=kubernetes \
  --user=dashboard_user \
  --kubeconfig=local-ngkeconk8s-1-21-admin.kubeconfig	    # 设置上下文参数
[root@master01 dashboard]# kubectl config use-context default --kubeconfig=local-ngkeconk8s-1-21-admin.kubeconfig         # 设置默认上下文

将web.odocker.com.crt证书文件导入,以便于浏览器使用该文件登录。

导入证书

将web.odocker.com证书导入浏览器,并设置为信任,导入操作略。

测试访问dashboard

本实验采用ingress所暴露的域名:https://web.odocker.com 方式一:token访问 可使用kubectl describe secret -n kubernetes-dashboard {ADMIN_SECRET} | grep -E '^token' | awk '{print 2}'所获取的token访问。

方式二:kubeconfig访问

local-ngkeconk8s-1-21-admin.kubeconfig文件访问。

提示:

更多dashboard访问方式及认证可参考附004.Kubernetes Dashboard简介及使用

dashboard登录整个流程可参考:https://www.cnadn.net/post/2613.html

Longhorn存储部署

Longhorn概述

Longhorn是用于Kubernetes的开源分布式块存储系统。

提示:更多介绍参考:https://github.com/longhorn/longhorn。

基础软件安装

代码语言:javascript
复制
[root@master01 ~]# source environment.sh
[root@master01 ~]# for all_ip in ${ALL_IPS[@]}
  do
    echo ">>> ${all_ip}"
    ssh root@${all_ip} "yum -y install iscsi-initiator-utils &"
  done

提示:所有节点都需要安装。

设置标签

代码语言:javascript
复制
[root@master01 ~]# kubectl label nodes master0{1,2,3} longhorn-ui=enabled

提示:ui图形界面可复用master高可用,因此部署在master节点。

准备磁盘

默认longhorn使用/var/lib/longhorn/作为设备路径,因此建议提前挂载。

代码语言:javascript
复制
[root@master01 ~]# source environment.sh
[root@master01 ~]# for node_ip in ${NODE_IPS[@]}
  do
    echo ">>> ${node_ip}"
        ssh root@${node_ip} "mkfs.xfs -f /dev/sdb &&
        mkdir -p /var/lib/longhorn/ &&
        echo '/dev/sdb        /var/lib/longhorn        xfs        defaults        0 0' >> /etc/fstab &&
        mount -a"
  done

配置Longhorn

代码语言:javascript
复制
[root@master01 ~]# mkdir longhorn
[root@master01 ~]# cd longhorn/
[root@master01 longhorn]# wget \
https://raw.githubusercontent.com/longhorn/longhorn/master/deploy/longhorn.yaml

[root@master01 longhorn]# vi longhorn.yaml
……
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app: longhorn-manager
  name: longhorn-manager
……
        imagePullPolicy: IfNotPresent
……
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: longhorn-ui
  name: longhorn-ui
……
      nodeSelector:
        longhorn-ui: enabled                        #追加标签选择
      tolerations:
        - key: node-role.kubernetes.io/master       #添加容忍
          effect: NoSchedule
#      imagePullSecrets:
#      - name:
……
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: longhorn-ui
  name: longhorn-frontend
  namespace: longhorn-system
spec:
  type: NodePort			                        #修改为nodeport
  selector:
    app: longhorn-ui
  ports:
  - port: 80
    targetPort: 8000
    nodePort: 30002
---
……

[root@master01 longhorn]# kubectl apply -f longhorn.yaml
[root@master01 longhorn]# kubectl -n longhorn-system get pods -o wide

提示:若部署异常可删除重建,若出现无法删除namespace,可通过如下操作进行删除:

代码语言:javascript
复制
wget https://github.com/longhorn/longhorn/blob/master/uninstall/uninstall.yaml
rm -rf /var/lib/longhorn/
kubectl apple -f uninstall.yaml
kubectl delete -f uninstall.yaml

动态sc创建

提示:默认longhorn部署完成已创建一个sc,也可通过如下手动编写yaml创建。

代码语言:javascript
复制
 [root@master01 longhorn]# kubectl get sc
NAME                   PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
……
longhorn               driver.longhorn.io      Delete          Immediate              true                   15m
代码语言:javascript
复制
[root@master01 longhorn]# cat <<EOF > longhornsc.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: longhornsc
provisioner: rancher.io/longhorn
parameters:
  numberOfReplicas: "3"
  staleReplicaTimeout: "30"
  fromBackup: "" 
EOF

[root@master01 longhorn]# kubectl apply -f longhornsc.yaml

测试PV及PVC

代码语言:javascript
复制
[root@master01 longhorn]# cat <<EOF > longhornpod.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: longhorn-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn
  resources:
    requests:
      storage: 500Mi

---
apiVersion: v1
kind: Pod
metadata:
  name: longhorn-pod
  namespace: default
spec:
  containers:
  - name: volume-test
    image: nginx:stable-alpine
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: volv
      mountPath: /data
    ports:
    - containerPort: 80
  volumes:
  - name: volv
    persistentVolumeClaim:
      claimName: longhorn-pvc
EOF
代码语言:javascript
复制
[root@master01 longhorn]# kubectl apply -f longhornpod.yaml
[root@master01 longhorn]# kubectl get pods
[root@master01 longhorn]# kubectl get pvc
[root@master01 longhorn]# kubectl get pv

Ingress暴露Longhorn

代码语言:javascript
复制
[root@master01 longhorn]# yum -y install httpd-tools
[root@master01 longhorn]# htpasswd -c auth xhy			#创建用户名和密码
New password: [输入密码]
Re-type new password:  [输入密码]

提示:也可通过如下命令创建:

代码语言:javascript
复制
USER=xhy; PASSWORD=x120952576; echo "${USER}:$(openssl passwd -stdin -apr1 <<< ${PASSWORD})" >> auth
代码语言:javascript
复制
[root@master01 longhorn]# kubectl -n longhorn-system create secret generic longhorn-basic-auth --from-file=auth

[root@master01 longhorn]# cat <<EOF > longhorn-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: longhorn-ingress
  namespace: longhorn-system
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: longhorn-basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required '
spec:
  rules:
  - host: longhorn.odocker.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: longhorn-frontend
            port: 
              number: 80
EOF
代码语言:javascript
复制
[root@master01 longhorn]# kubectl apply -f longhorn-ingress.yaml
[root@master01 longhorn]# kubectl -n longhorn-system get ingress
NAME               CLASS    HOSTS                  ADDRESS                                  PORTS   AGE
longhorn-ingress   <none>   longhorn.odocker.com   172.24.8.144,172.24.8.145,172.24.8.146   80      45s

确认验证

浏览器访问:longhorn.odocker.com,并输入账号和密码。

使用xhy/密码登录查看。

Helm部署

前置准备

Helm 将使用 kubectl 在已配置的集群上部署 Kubernetes 资源,因此需要如下前置准备:

  • 正在运行的 Kubernetes 集群;
  • 预配置的 kubectl 客户端和 Kubernetes 集群正确交互。

二进制安装Helm

代码语言:javascript
复制
[root@master01 ~]# wget https://get.helm.sh/helm-v3.5.4-linux-amd64.tar.gz
[root@master01 ~]# tar -zxvf helm-v3.5.4-linux-amd64.tar.gz
[root@master01 ~]# cp linux-amd64/helm /usr/local/bin/

[root@master01 ~]# helm version		#查看安装版本
[root@master01 ~]# echo 'source <(helm completion bash)' >> $HOME/.bashrc	#helm自动补全

提示:更多安装方式参考官方手册:https://helm.sh/docs/intro/install/。

Helm操作

查找chart

helm search:可以用于搜索两种不同类型的源。

helm search hub:搜索 Helm Hub,该源包含来自许多不同仓库的Helm chart。

helm search repo:搜索已添加到本地头helm客户端(带有helm repo add)的仓库,该搜索是通过本地数据完成的,不需要连接公网。

代码语言:javascript
复制
[root@master01 ~]# helm search hub			            #可搜索全部可用chart
[root@master01 ~]# helm search hub wordpress

添加repo

代码语言:javascript
复制
[root@master01 ~]# helm repo list			            #查看repo
[root@master01 ~]# helm repo add brigade https://brigadecore.github.io/charts
[root@master01 ~]# helm repo add stable https://kubernetes-charts.storage.googleapis.com/   #添加官方repo
[root@master01 ~]# helm repo add bitnami https://charts.bitnami.com/bitnami

[root@master01 ~]# helm search repo brigade
[root@master01 ~]# helm search repo stable		        #搜索repo中的chart
[root@master01 ~]# helm repo update			            #更新repo的chart

扩展:集群扩容及缩容

集群扩容

  • master节点扩容 参考:添加Master节点 步骤
  • worker节点扩容 参考:添加Worker节点 步骤

集群缩容

  • master节点缩容
代码语言:javascript
复制
[root@master01 ~]# kubectl drain master03 --delete-emptydir-data --force --ignore-daemonsets
[root@master01 ~]# kubectl delete node master03

[root@master03 ~]# kubeadm reset -f && rm -rf $HOME/.kube
  • worker节点缩容
代码语言:javascript
复制
[root@master01 ~]# kubectl drain worker04 --delete-emptydir-data --force --ignore-daemonsets
[root@master01 ~]# kubectl delete node worker04

[root@worker04 ~]# kubeadm reset -f && rm -rf $HOME/.kube
[root@worker04 ~]# rm -rf /etc/kubernetes/admin.conf /etc/kubernetes/kubelet.conf /etc/kubernetes/bootstrap-kubelet.conf /etc/kubernetes/controller-manager.conf /etc/kubernetes/scheduler.conf
下一篇
举报
领券