Centos7系统20.10.9版本docker安装1.22.12版本kubelet集群部署,kubespherev4.1.3(新版本安装,超详细安装步骤)
centos7系统,三台机器部署kubernetes集群以及部署kubesphere
一、环境准备
0)、生产环境云服务器防火墙配置
1、配置安全组,保证即便没有配置各个机器之间的端口,也能保证机器之间是互通的

2、各个机器内部额外配置端口,保证外部可以访问使用

3、k8s集群自动在机器上暴露节点设置
配置个起始端口的区间,30000-32767之间,以后未来k8s部署应用,那么就不需要配置其它端口了,比如nginx的8端口,因为nginx会以service的形式统一管理,而service的端口可以分配在30000-32767之间,直接请求serveice的端口,k8s会以负载均衡的方式分配给nginx,这样就不需要配置那么多端口了
1)、环境准备
分别修改三台机器的主机名称(所有节点执行),注意是各自改各自机器上的hostname,别搞错了
hostnamectl set-hostname k8s-node1 && bash
hostnamectl set-hostname k8s-node2 && bash
hostnamectl set-hostname k8s-node3 && bash
配置主机hosts文件,相互之间通过主机名互相访问
修改每台服务器的/etc/hosts文件,文件最后增加如下内容:
ps. 文件里原有的配置不要动(所有节点执行)
## 192.168.10.100节点
192.168.10.100 k8s-node1
192.168.10.101 k8s-node2
192.168.10.102 k8s-node3
## 192.168.10.101节点
192.168.10.100 k8s-node1
192.168.10.101 k8s-node2
192.168.10.102 k8s-node3
## 192.168.10.102节点
192.168.10.100 k8s-node1
192.168.10.101 k8s-node2
192.168.10.102 k8s-node3
关闭交换分区swap,建议永久关闭(所有节点执行)
#临时关闭
swapoff -a
永久关闭:注释swap挂载,给swap这行开头加一下注释。为什么要关闭swap交换分区?
Swap是交换分区,如果机器内存不够,会使用swap分区,但是swap分区的性能较低,k8s设计的时候为了能提升性能,默认是不允许使用交换分区的。Kubeadm初始化的时候会检测swap是否关闭,如果没关闭,那就初始化失败。如果不想要关闭交换分区,安装k8s的时候可以指定–ignore-preflight-errors=Swap来解决
#永久关闭
vi /etc/fstab
#或者使用二选一
sed -ri 's/.*swap.*/#&/' /etc/fstab
free -g #验证,swap 必须为 0;

关闭防火墙 生产环境不能关闭,要配置防火墙规则,允许kubelet端口通过
systemctl stop firewalld
#关闭防火墙开机自启
systemctl disable firewalld
关闭selinux,不关闭配置集群会有问题
#临时关闭
sudo setenforce 0
#永久关闭
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
配置集群时间同步(所有节点执行)
#安装日期软件(所有节点都执行)
yum install -y chrony
如果使用yum出现以下异常:
已加载插件:fastestmirror, langpacks
Determining fastest mirrors
Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=7&arch=x86_64&repo=os&infra=stock error was
14: curl#6 - "Could not resolve host: mirrorlist.centos.org; 未知的错误"
One of the configured repositories failed (未知),
and yum doesn't have enough cached data to continue. At this point the only
safe thing yum can do is fail. There are a few ways to work "fix" this:
1. Contact the upstream for the repository and get them to fix the problem.
2. Reconfigure the baseurl/etc. for the repository, to point to a working
upstream. This is most often useful if you are using a newer
distribution release than is supported by the repository (and the
packages for the previous distribution release still work).
3. Run the command with the repository temporarily disabled
yum --disablerepo=<repoid> ...
4. Disable the repository permanently, so yum won't use it by default. Yum
will then just ignore the repository until you permanently enable it
again or use --enablerepo for temporary usage:
yum-config-manager --disable <repoid>
or
subscription-manager repos --disable=<repoid>
5. Configure the failing repository to be skipped, if it is unavailable.
Note that yum will try to contact the repo. when it runs most commands,
so will have to try and fail each time (and thus. yum will be be much
slower). If it is a very temporary problem though, this is often a nice
compromise:
yum-config-manager --save --setopt=<repoid>.skip_if_unavailable=true
Cannot find a valid baseurl for repo: base/7/x86_64
解决办法:
1.下载阿里云 CentOS 7 镜像源
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
2.清除缓存并生成新缓存
yum clean all
yum makecache
#修改配置文件(master节点)
vim /etc/chrony.conf
# 配置上游NTP服务器(从互联网获取时间)
server 0.pool.ntp.org iburst
server 1.pool.ntp.org iburst
server 2.pool.ntp.org iburst
server 3.pool.ntp.org iburst
# 允许本地网络设备同步时间(根据实际网络调整)
allow 192.168.0.0/16 # 允许192.168.0.0/16网段的客户端
# allow 10.0.0.0/8 # 取消注释以允许10.0.0.0/8网段(示例)
# 本地时钟作为备用时间源(当无法访问上游服务器时使用)
local stratum 10
# 指定存放时间数据的目录
driftfile /var/lib/chrony/drift
# 启用RTCCLOCK内核模块(硬件时钟同步)
rtcsync
# 保存频率,减少系统崩溃时的时间损失
makestep 1.0 3
# 指定日志文件位置
logdir /var/log/chrony
# 配置防火墙(如启用),没有启动防火墙就不需要配置这一步
firewall-cmd --add-service=ntp --permanent
firewall-cmd --reload
# 启动并验证 chrony 服务
# 启动chrony服务
systemctl start chronyd
# 设置开机自启
systemctl enable chronyd
# 检查服务状态
systemctl status chronyd
# 验证时间同步状态
chronyc sources -v
# 正常输出示例
210 Number of sources = 4
.-- Source mode '^' = server, '=' = peer, '#' = local clock
/ .- Source state '*' = current synced, '+' = combined, '-' = not combined,
| / '?' = unreachable, 'x' = time may be in error, '~' = time too variable
|| .- xxxx [ yyyy ] +/- zzzz
|| .- Reachability register (octal)
|| | .- xxxx [ yyyy ] +/- zzzz
|| | | .- xxxx = adjusted offset, yyyy = measured offset, zzzz = estimated error
|| | | |
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^* 2.pool.ntp.org 2 6 377 12 -12us[ -12us] +/- 12ms
^+ 3.pool.ntp.org 2 6 377 11 +33us[ +33us] +/- 11ms
^+ 0.pool.ntp.org 2 6 377 12 -15us[ -15us] +/- 11ms
^+ 1.pool.ntp.org 2 6 377 12 +23us[ +23us] +/- 11ms
从节点配置,如果从节点没有安装chrony,就需要先安装yum install -y chrony
vim /etc/chrony.conf
# 注释掉原有服务器配置
# server 0.centos.pool.ntp.org iburst
# server 1.centos.pool.ntp.org iburst
# server 2.centos.pool.ntp.org iburst
# server 3.centos.pool.ntp.org iburst
# 添加你的chrony服务器
server 192.168.10.100 iburst
allow 192.168.10.0/24 # 允许192.168.10.0/24网段的客户端
#配置防火墙(如启用),没有启用防火墙不需要配置这一步
firewall-cmd --permanent --add-service=ntp
firewall-cmd --reload
# 重启chrony服务
systemctl restart chronyd
# 设置开机自启
systemctl enable chronyd
# 检查服务状态
systemctl status chronyd
验证时间同步状态
chronyc sources -v
210 Number of sources = 1
.-- Source mode '^' = server, '=' = peer, '#' = local clock
/ .- Source state '*' = current synced, '+' = combined, '-' = not combined,
| / '?' = unreachable, 'x' = time may be in error, '~' = time too variable
|| .- xxxx [ yyyy ] +/- zzzz
|| .- Reachability register (octal)
|| | .- xxxx [ yyyy ] +/- zzzz
|| | | .- xxxx = adjusted offset, yyyy = measured offset, zzzz = estimated error
|| | | |
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^* 192.168.10.100 3 6 377 10 -6us[ -6us] +/- 25ms

将桥接的IPv4流量传递到iptables的链(所有节点执行):
cat << EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
cat << EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system
yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
设置镜像加速地址(所有节点执行)
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
配置ssh免密登录(master节点)
先生成密钥,再复制到所有节点
ssh-keygen
#hosts配置的
ssh-copy-id k8s-node1
ssh-copy-id k8s-node2
ssh-copy-id k8s-node3
#测试连接
ssh k8s-node3
二、docker20.10.7版本安装
1)、安装docker(所有节点都执行)
sudo yum remove docker*
yum install docker-ce-20.10.7 docker-ce-cli-20.10.7 containerd.io-1.4.6
2)、配置 docker 加速(所有节点都执行)
vi /etc/docker/daemon.json
{
"registry-mirrors": ["https://shj9hb93.mirror.aliyuncs.com","https://docker.registry.cyou",
"https://docker-cf.registry.cyou",
"https://dockercf.jsdelivr.fyi",
"https://docker.jsdelivr.fyi",
"https://dockertest.jsdelivr.fyi",
"https://mirror.aliyuncs.com",
"https://dockerproxy.com",
"https://mirror.baidubce.com",
"https://docker.m.daocloud.io",
"https://docker.nju.edu.cn",
"https://docker.mirrors.sjtug.sjtu.edu.cn",
"https://docker.mirrors.ustc.edu.cn",
"https://mirror.iscas.ac.cn",
"https://docker.rainbond.cc"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
3)、启动 docker & 设置 docker 开机自启(所有节点都执行)
sudo systemctl daemon-reload
systemctl start docker
systemctl enable docker
4)、添加阿里云 yum 源(所有节点都执行)
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
如果有安装最新版本docker需求或者docker往下降版本
1)、要下载最新版本的docker命令,升级docker版本可以直接执行
sudo yum install -y docker-ce docker-ce-cli containerd.io
2)、高版本docker需要降级安装旧版本docker,新版本往下降,需要执行下面命令,如果是旧版本往上升级,直接执行下载安装docker的命令就可以了
sudo yum remove docker-buildx-plugin
执行安装命令
#将版本改成你需要的旧版本
yum install docker-ce-20.10.9-3.el7 docker-ce-cli-20.10.9-3.el7 docker-compose-plugin containerd.io
#启动docker
systemctl start docker
#设置开机自启
systemctl enable docker

可以看到,我这里docker启动失败了
排查docker启动失败几种方式
1)、检查 containerd 服务状态
systemctl status containerd.service
我这里是正常启动的,如果没有启动,则启动它
systemctl start containerd.service
2)、设置 containerd 服务开机自启
systemctl enable containerd.service
3)、检查 Docker 配置文件,Docker 的配置文件(通常为 /etc/docker/daemon.json)可能存在语法错误或不兼容的配置项,从而导致 Docker 守护进程启动失败
sudo mv /etc/docker/daemon.json /etc/docker/daemon.json.bak
这一步是为了在修改配置文件出现问题时可以恢复。重新启动 Docker 服务:
sudo systemctl start docker.service
若 Docker 服务能够正常启动,说明原配置文件存在问题。你可以逐步将原配置项添加回新的 daemon.json 文件中,每次添加后都重启 Docker 服务,以确定具体是哪个配置项导致的问题。我这里就是daemon.json格式有问题,修复完以后

3)、再次启动docker,然后使用systemctl status docker,就可以看到启动成功了

5)、docker配置镜像下载加速器,添加/修改了镜像加速器,记得让docker重新加载一下,先执行加速器地址配置命名,后执行docker加载命令,位置在/etc/docker/daemon.josn(所有节点执行)
vi /etc/docker/daemon.josn
{
"registry-mirrors": ["https://shj9hb93.mirror.aliyuncs.com","https://docker.registry.cyou",
"https://docker-cf.registry.cyou",
"https://dockercf.jsdelivr.fyi",
"https://docker.jsdelivr.fyi",
"https://dockertest.jsdelivr.fyi",
"https://mirror.aliyuncs.com",
"https://dockerproxy.com",
"https://mirror.baidubce.com",
"https://docker.m.daocloud.io",
"https://docker.nju.edu.cn",
"https://docker.mirrors.sjtug.sjtu.edu.cn",
"https://docker.mirrors.ustc.edu.cn",
"https://mirror.iscas.ac.cn",
"https://docker.rainbond.cc"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
重新加载配置,重启docker
sudo systemctl daemon-reload
#重启docker
systemctl restart docker
三、安装kubelet(主节点,我这里是三台机器,任选一个作为主节点)
1)、下载kubelet前,要先配置它的加速器地址,不然下载的时候就会去kubelet官网地址下载。(所有节点都执行)
sudo vi /etc/yum.repos.d/kubernetes.repo
#添加以下内容
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
2)、安装kubelet,版本是1.22.12(所有节点都执行)
kubeadm:用来初始化k8s集群的指令。
kubelet:在集群的每个节点上用来启动 Pod 和容器等。
kubectl:用来与k8s集群通信的命令行工具,查看、创建、更新和删除各种资源
mkdir /root/k8s/kubernetesv1.22.12/
cd /root/k8s/kubernetesv1.22.12/
yum install -y kubelet-1.22.12 kubeadm-1.22.12 kubectl-1.22.12
#设置开机自启,必须要设置
sudo systemctl enable kubelet
#启动kubelet
sudo systemctl start kubelet
3)、初始化kubeadm(只在master节点执行)
sudo kubeadm init \
--apiserver-advertise-address=192.168.10.100 \
--image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--kubernetes-version v1.22.12 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=10.244.0.0/16

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
也可以使用这个命令查看所有yum安装的应用
yum list|grep kube

4)、安装网络插件Calico(主节点执行)
这个是安装在 Kubernetes 集群中部署 网络插件,我在根目录创建了一个k8s的目录,进入该目录执行命令下载calico.yml,执行完该命令后就会看到k8s目录里多个文件。注意,安装网络插件一定要在初始化kubeadm后
mkdir /root/k8s/calicov3.15/
cd /root/k8s/calicov3.15/
下载calico.yml保存
curl https://docs.projectcalico.org/v3.15/manifests/calico.yaml -O
#或者使用
wget https://docs.projectcalico.org/v3.15/manifests/calico.yaml
修改配置,显示文件内容行数,进入文件后不要按i,直接输入冒号:set number,就会显示行数
如果文件内容很多,想快速定位到3727行,按一下ESC,然后直接输入3727G点回车(注意,linux界面,输入
修改配置
3727行 - name: CALICO_IPV4POOL_CIDR
3728行 value: "10.244.0.0/16" # 与 kubeadm init 时的 --pod-network-cidr 一致
安装至kubectl
kubectl apply -f calico.yaml
验证是否成功
kubectl get pod -A | grep calico
5)、前面初始化kubelet控制台出现的token,这个token是会过期的,只有24小时有效,再执行上面的命令会有问题,可以执行一个命令再生成一个永不过期的token,(而且只能在从节点执行),如果在24小时内执行从节点加入主节点命令,则第五步可以跳过不需要执行。
该命令用于创建一个新的令牌(token),此令牌在节点加入集群时会被使用,作为身份验证的凭证。打印的一长串,kubeadm join …这个命令是可以直接执行的,作用是在节点加入集群时会被使用,简单点说就是让其他节点,都加入主节点进来
–ttl 0:ttl 是 “Time To Live” 的缩写,代表令牌的有效期。将其设置为 0,意味着生成的令牌永不过期。在实际使用时,如果不确定新节点何时加入集群,设置为永不过期是比较方便的做法。
kubeadm token create --ttl 0 --print-join-command
执行完上面这个重新生成token的命令后,控制台会继续打印出这个token,注意,直接复制控制台这个token,第二行calico.yaml --discovery-token-ca-cert-hash sha256:bb481e918e79f2de49519209cffcba81fb41b4702dea705c2d0a8178a1c06f14 ,一定要删除calico.yaml,不然执行从节点加入主节点会报错
kubeadm join <主节点 IP>:<端口> --token <令牌> --discovery-token-ca-cert-hash sha256:<哈希值>
kubeadm join 你的主机ip:端口号--token 1xt7bj.r3vzi4l0vzdq4ary \
--discovery-token-ca-cert-hash sha256:d5450edfa03899712abb11e2a95cb4c6867b56e9f6edfaf7cdc06d1646090f59
6)、查看所有的节点信息命令
kubectl get nodes
可以看到我这里不是Ready状态,需要等待一会

我这里目前只有一个节点,就是master节点,一定要等master节点的状态是Ready
7)、部署kubelet从节点
1)、两台机器执行加入主节点命令
注意啊,直接从控制台复制,第二行会多出来一个calico.yaml,记得删除它
kubeadm join 你的主机ip:端口号--token elkh0e.y76q4glo87dkkpim \
--discovery-token-ca-cert-hash sha256:5ba04add15ccbe3fcf61eae1de00412bb2eeae21610ab7b47608205a8e21e9b3

3)、两台机器都加入集群后,在主节点查看一下从节点状态
kubectl get nodes

可以看到,两个从节点也加入到集群中了,k8s-node1是master节点,但是另外两个节点的状态是NotReady的,这是因为,从节点还正在初始化中
8)、master监控Node各节点
当这各个节点状态都是Running了,再去查看从节点的状态
watch kubectl get pod -n kube-system -o wide

可以看到,集群所有的节点状态都是Ready了
四、存储抽象NFS(网络文件系统)
在docker中,以前是将docker内部目录挂载到机器上,但是在k8s中如果将目录挂载到机器上,如果某个节点的容器挂了,比如MySQL,k8s的自愈机制会在其它节点再拉起一份,那就会导致原来的数据丢失了,所以在k8s中需要应用到存储层:比如NFS、OpenEBS,k8s会将这些容器的数据全部存在存储层,而这个存储层会在所有节点都有一份
方式一:使用openEBS(推荐这个)
0、为什么推荐openEBS
我前面是使用nfs做存储系统的,但是到了部署MySQL的时候,看部署日志kubectl logs -n <名称空间> 发现mysql初始化很慢(下面贴图展示)初始化半天,等很久后初始化完成,mysql也会有各种各样的问题,比如无法使用DNS域名访问,提示没有权限,是因为在初始化MySQL的时候,少了很多东西。而且opendEBS是块存储,这种类型的比NFS存储性能更高,效率更快。MySQL、redis这种中间件也是集群部署的,也不用担心数据丢失问题
1、下载helm
curl -fsSL -o helm-v3.12.3-linux-amd64.tar.gz https://get.helm.sh/helm-v3.12.3-linux-amd64.tar.gz
2、解压并且验证安装
# 解压文件
tar -zxvf helm-v3.12.3-linux-amd64.tar.gz
# 移动二进制文件到PATH路径
sudo mv linux-amd64/helm /usr/local/bin/helm
# 验证安装
helm version

3、添加仓库
# 添加官方稳定仓库
helm repo add stable https://charts.helm.sh/stable
helm repo add openebs https://openebs.github.io/charts
# 更新仓库索引
helm repo update

5、安装opendEBS
helm install openebs openebs/openebs \
--namespace openebs \
--create-namespace \
--version 2.10.0
查看安装的openebs的pod
kubectl get pods -n openebs

6、查看存储类
等待openebs所有的pod都是Running状态后,查看存储类,可以使用linux系统自带的每秒输出指令的内容,用来监控openebs是否都是Running
watch -n 1 kubectl get pod -n openebs
#查看openebs的存储类
kubectl get sc

7、设置默认存储类
必须要设置默认存储类,不然安装kubesphere的时候,会报错,找不到默认存储类
kubectl patch storageclass openebs-hostpath -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

方式二:安装nfs
1、所有节点都执行
yum install -y nfs-utils
2、master节点执行
#在master节点暴露/nfs/data/这个目录
#*:所有人都能同步这个目录,以非安全、读写的模式同步
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
mkdir -p /nfs/data
systemctl enable rpcbind
systemctl enable nfs-server
systemctl start rpcbind
systemctl start nfs-server
#配置生效
exportfs -r
检查/nfs/data这个目录暴露在外面
exportfs

到这里,nfs的服务端已经启动好了
3、从节点
#使用该命令查看master节点有哪些目录可以挂载
#这里应该是你自己的IP
showmount -e 192.168.10.100

#给所有的从节点创建一个跟master节点相同的目录
mkdir -p /nfs/data
#执行以下命令挂载nfs远程服务器上的共享目录到本机路径 /nfs/data
mount -t nfs 192.168.10.100:/nfs/data /nfs/data
4、测试NFS的主从同步
master节点新建文件
#验证从节点是否已经挂载了远程服务器的目录,可以在mster写入一个测试文件,
#然后去从节点的相同目录/nfs/data/下查看,是否有这个新建的文件
echo "hello nfs server" > /nfs/data/test.txt

从节点查看是否有这个文件,并且输出文件内容
方式一:学习以及简单使用什么是NFS(master节点执行)
1)、为什么要使用NFS?
使用原生方式数据挂载,将某个容器的目录挂载到NFS文件系统上,比如下面这个将nginx的数据目录挂载到NFS
vi deploy.yaml
#下面的ip需要改成你的master节点ip
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-pv-demo
name: nginx-pv-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx-pv-demo
template:
metadata:
labels:
app: nginx-pv-demo
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html # 挂载目录
volumes:
# 和 volumeMounts.name 一样
- name: html
nfs:
# master IP
server: 192.168.10.100 #master节点ip
path: /nfs/data/nginx-pv # 要提前创建好文件夹,否则挂载失败
cd /nfs/data
mkdir -p nginx-pv
ls
kubectl apply -f deploy.yaml
cd /nfs/data/
ls
cd nginx-pv/
echo "cgxin" > index.html
# 进入 pod 里面查看
问题:占用空间,删掉之后,文件还在,内容也在,而且还是没法管理大小的
2)、PV和PVC
1)、PV和PVC的概念
PV:持久卷(Persistent Volume),将应用需要持久化的数据保存到指定位置。
PVC:持久卷申明(Persistent Volume Claim),申明需要使用的持久卷规格。
通俗讲:持久卷就是数据需要存储到的位置,持久卷申明就是pod需要写一份申请书这个申请书就是PVC,去申请多大的空间,申请一兆,那么就开一份一兆的实体化存储的PV空间。所以当这个pod被删除后,这个PVC申请书也会带着一起被删除,PVC删除后,申请的实体化PV存储空间也会被回收。挂载目录。ConfigMap 挂载配置文件。 这里是 是 静态的, 就是自己创建好了 容量,然后 PVC 去挑。 还有 动态供应的,不用手动去创建 PV池子
3)、创建PV
1、创建 PV 池
静态供应
# 在 nfs主节点(master服务器) 执行
mkdir -p /nfs/data/01
mkdir -p /nfs/data/02
mkdir -p /nfs/data/03
使用pv.yaml 创建 3个 PV
vi pv.yaml
#下面有三个ip,需要改成你的master节点ip
apiVersion: v1
kind: PersistentVolume
metadata:
# 这个name 要小写,如 Gi 大写就不行
name: pv01-10m
spec:
# 限制容量必须是大写
capacity:
storage: 10M
# 读写模式:可读可写
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
# 挂载 上面创建过的文件夹
path: /nfs/data/01
# nfs 主节点服务器的 IP
server: 192.168.10.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
# 这个name 要小写,如 Gi 大写就不行
name: pv02-1gi
spec:
capacity:
# 限制容量必须是大写
storage: 1Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/02
# nfs 主节点服务器的 IP
server: 192.168.10.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
# 这个name 要小写,如 Gi 大写就不行
name: pv03-3gi
spec:
capacity:
# 限制容量必须是大写
storage: 3Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/03
# nfs 主节点服务器的 IP
server: 192.168.10.100
kubectl apply -f pv.yaml
#获取资源,看看系统有多少种资源
kubectl get persistentvolume
#或者使用
kubectl get pv
可以看到10M、1G、3G的资源池
4)、PVC创建与绑定
相当于创建设用pv的申请书
vi pvc.yaml
#直接拷贝使用
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
# 需要 200M的 PV
storage: 200Mi
# 上面 pv.yaml中storageClassName写的什么 这里就写什么
#这个storageClassName相当于是一个分组,上面nfs下有三个不同大小存储空间,下面使用
#nfs,就会去pv找nfs的分组,在nfs分组下找一个合适它的存储空间,这里申请的是200兆,所以就会申请1G的空间
storageClassName: nfs
使用命令
kubectl get pv
这个STATUS状态为Available的。表示这个pv没有人使用,可以使用
kubectl apply -f pvc.yaml
再次使用命令,查看pv
kubectl get pv
可以看到,这个1G的空间,状态已经变为Bound,这个空间被default/nginx-pvc使用了(默认名称空间下的nginx-pvc);10M 不够,3G太大,就选择了 1G;;如果删除这个pvc再重新应用,1G的还处在释放中,这个时候会去绑定3G的空间
5)、创建 Pod 绑定 PVC
vi pod-banding-pvc.yaml
#直接拷贝使用
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-deploy-pvc
name: nginx-deploy-pvc
spec:
replicas: 2
selector:
matchLabels:
app: nginx-deploy-pvc
template:
metadata:
labels:
app: nginx-deploy-pvc
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
# 之前是 nfs,这里用 pvc,就是前面申请的pvc空间名称
persistentVolumeClaim:
claimName: nginx-pvc
kubectl get pod
两个nginx的pod创建好了
查看pvc的绑定关系
kubectl get pvc

查看pvc和pv
kubectl get pvc,pv

到这里就看到,目录挂载成功了,后面如果要修改pod被挂载的目录内容,就可以直接在外面的/nfs/data/02目录修改就可以了
6)、使用ConfigMap配置集部署redis测试pvc挂载
1、准备ConfigMap ★
ConfigMap:抽取应用配置,并且可以自动更新。挂载配置文件, PV 和 PVC 是挂载目录的。
vi redis.conf
# 写
appendonly yes
# 创建配置,redis保存到k8s的etcd;
#使用kubectl create命令创建一个ConfigMap(配置集),以后专门管理所有的配置
#生成的这个k8s配置集,是在etcd存的
kubectl create cm redis-conf --from-file=redis.conf
# 查看配置集
kubectl get cm
#前面生成的redis.conf可以删除了,因为使用kubectl create命令已经生成了一个k8s可以直接使用的配置集
rm -rf redis.conf
查看生成的这个redis-conf配置集内容
kubectl get cm redis-conf -oyaml
#修改cm配置集
kubectl edit cm redis-conf
apiVersion: v1
# data是所有真正的数据,key:默认是文件名 value:配置文件的内容(appendonly yes 这个值是前面删除的redis.conf文件内容,该文件内容随便写的)
data:
redis.conf: |
appendonly yes
kind: ConfigMap
metadata:
creationTimestamp: "2025-06-12T11:38:25Z"
name: redis-conf
namespace: default
resourceVersion: "392472"
uid: 4aa3aed8-0600-43c8-a5d6-ad97d62aa632

2、创建redis的Pod
准备yaml文件
vi redis.yaml
#直接拷贝使用
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
command:
# 启动命令
- redis-server
# 指的是redis容器内部的位置
- "/redis-master/redis.conf"
ports:
- containerPort: 6379
volumeMounts:
- mountPath: /data
name: data
- mountPath: /redis-master
name: config
volumes:
- name: data
emptyDir: {}
- name: config
configMap:
#这个redis-conf就是前面cm生成的配置文件
name: redis-conf
items:
- key: redis.conf
path: redis.conf
kubectl apply -f redis.yaml
kubectl get pod

3、在bashboard页面中进入redis容器内部

4、查看 redis.conf 配置文件 内容,可以i看到,就是最开始创建redis.conf文件时添加的内容

5、修改cm的Pod内容
kubectl get cm
# 修改配置 里 redis.conf 的内容,在里面随意修改成其它东西
kubectl edit cm redis-conf


修改 redis-conf 的 redis.conf 内容,过了一会, 就同步了
6、测试进入redis容器内部
kubectl exec -it redis -- redis-cli

方式二:配置动态供应的默认存储类(生产环境使用,master节点执行)
注意:如果你前面使用方式一安装过NFS,需要把NFS清理干净,如果担心有残留,直接重置系统
1、配置动态供应的默认存储类(注意下面两处的ip修改为自己master节点的ip)
vi sc.yaml
## 创建了一个存储类,下面有两个地方的ip需要改成你的master节点IP
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storage
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
archiveOnDelete: "true" ## 删除pv的时候,pv的内容是否要备份
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/nfs-subdir-external-provisioner:v4.0.2
# resources:
# limits:
# cpu: 10m
# requests:
# cpu: 10m
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: k8s-sigs.io/nfs-subdir-external-provisioner
- name: NFS_SERVER
value: 139.198.171.181 ## 指定自己nfs服务器地址
- name: NFS_PATH
value: /nfs/data ## nfs服务器共享的目录
volumes:
- name: nfs-client-root
nfs:
server: 139.198.171.181
path: /nfs/data
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
2、应用sc.yaml
kubectl apply -f sc.yaml
3、使用命令查看默认存储类
kubectl get storageclass
就可以看到有一个默认的nfs-storage存储类,这个存储类的作用就是使用nfs进行存储,以后写的申请书可以动态的创建空间(也叫动态供应),方式一是需要自己先创建好空间比如方式一中01,02,03三个空间,这叫静态空间
4、测试动态供应空间
kubectl get pod -A
需要这个default名称空间的状态是Running
vi pvc.yaml
#直接拷贝使用
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
# 需要 200M的 PV
storage: 200Mi
#方式一中是有这段配置的,那是因为我这边是先安装的kubesphere,
#它默认存储类不是nfs,所以需要这段配置来指定存储类,这个配置也可以加上,
#只是value值就应该上面sc.yaml中指定的name名字nfs-storage(metadata:name: nfs-storage)
storageClassName: nfs-storage
kubectl apply -f pvc.yaml
kubectl get pvc
kubectl get pv
可以看到,这里直接就创建了一个200M的空间,并且是绑定状态,绑定到nginx-pvc中。到这里nfs就创建好了
五、安装metrics-server
metrics-server概念:是集群指标监控组件,比如CPU、内存占用率
1、准备metrics-server的yaml文件
vi metrics-server.yaml
#直接拷贝,不需要改任何东西
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-view: "true"
name: system:aggregated-metrics-reader
rules:
- apiGroups:
- metrics.k8s.io
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
rules:
- apiGroups:
- ""
resources:
- pods
- nodes
- nodes/stats
- namespaces
- configmaps
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server-auth-reader
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server:system:auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:metrics-server
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
ports:
- name: https
port: 443
protocol: TCP
targetPort: https
selector:
k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
selector:
matchLabels:
k8s-app: metrics-server
strategy:
rollingUpdate:
maxUnavailable: 0
template:
metadata:
labels:
k8s-app: metrics-server
spec:
containers:
- args:
- --cert-dir=/tmp
- --kubelet-insecure-tls
- --secure-port=4443
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/metrics-server:v0.4.3
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /livez
port: https
scheme: HTTPS
periodSeconds: 10
name: metrics-server
ports:
- containerPort: 4443
name: https
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /readyz
port: https
scheme: HTTPS
periodSeconds: 10
securityContext:
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
volumeMounts:
- mountPath: /tmp
name: tmp-dir
nodeSelector:
kubernetes.io/os: linux
priorityClassName: system-cluster-critical
serviceAccountName: metrics-server
volumes:
- emptyDir: {}
name: tmp-dir
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
labels:
k8s-app: metrics-server
name: v1beta1.metrics.k8s.io
spec:
group: metrics.k8s.io
groupPriorityMinimum: 100
insecureSkipTLSVerify: true
service:
name: metrics-server
namespace: kube-system
version: v1beta1
versionPriority: 100
kubectl apply -f metrics-server.yaml
kubectl get pod -A
等待这个metrics-server的Pod启动成功
2、查看所有节点CPU、内容占用率
kubectl top nodes
可以看到master节点cpu已经占用到了86了,这里m的换算率是,1000M差不多是一核
3、查看某个节点所有的Pod的CPU、内存占用率
kubectl top pods -A
可以看到master节点cpu占用率最高的pod是calico网络插件
六、使用阿里云私有镜像仓库,docker hub无法访问
1)、创建阿里云镜像仓库地址
控制台选择容器镜像服务
2)、创建个人版本实例
步骤:【实例列表】 ===》【创建个人实例】 ===》【设置Registry登录密码】这个Registry登录密码就是后面在服务器使用docker login登录时所需要的密码
3)、创建名称空间



4)、测试向阿里云镜像仓库推送镜像
创建完镜像仓库以后有仓库列表,点击刚刚创建的仓库,进入后在基本信息可以看到相关docker命令

5)、查找私有镜像仓库的凭证,用于在k8s中生成密钥

6)、在私有仓库拉取镜像
1、使用kubectl命令创建私有仓库的密钥
前面有介绍怎么找阿里云镜像仓库用户名以及地址
kubectl create secret docker-registry regcred \
--docker-server=<你的镜像仓库服务器> \
--docker-username=<你的用户名> \
--docker-password=<你的密码> \
--docker-email=<你的邮箱地址>
<secret-name>:自己定义的secret名字,也就是前面创建的镜像仓库名称
<your-registry>:阿里云镜像仓库地址
<your-username>:阿里云镜像仓库用户名
<your-password>:阿里云镜像仓库密码
<your-email>:邮箱
2、测试拉取阿里云仓库镜像
docker pull <阿里云镜像仓库地址>

七、安装语言环境Helm
1)、去除主节点的污点 kubectl describe node <你的hostname名字>;污点:【污点,就是不让master可以部署。去掉后就可以部署了】
kubectl describe node k8s-node1 | grep Taint
#去掉 master 节点的 Taint
kubectl taint nodes k8s-node1 node-role.kubernetes.io/master:NoSchedule-
2)、Helm安装
mkdir /root/k8s/helmv3.8.2/
cd /root/k8s/helmv3.8.2/
#下载Helm的压缩包文件
wget https://get.helm.sh/helm-v3.8.2-linux-amd64.tar.gz
# 解压
tar -zxvf helm-v3.8.2-linux-amd64.tar.gz
# 将 helm 二进制文件移动到 PATH 目录
mv linux-amd64/helm /usr/local/bin/
# 验证版本
helm version --short
# 输出应为: v3.8.2+g5ab6a61
yum install -y socat
3)、添加国内镜像源仓库
helm repo add kubesphere https://charts.kubesphere.io/main
#等待一会输出 "kubesphere" has been added to your repositories

更新仓库
helm repo update
#验证仓库中有哪些ks-core的版本
helm search repo kubesphere/ks-core --versions
#查看helm中所有kubesphere的版本
helm search repo kubesphere --versions | grep -E "kubesphere|ks-core"

4)、我看很多文档上Helm服务是3.X版本的,还在安装Tiller,Helm3.X已经不需要安装Tiller了。Helm 3 与 Helm 2 相比有较大的架构变化,Helm 3 将 Tiller 移除了。在 Helm 2 中,Tiller 是服务端组件,负责在 Kubernetes 集群中安装、升级、删除等操作,但由于 Tiller 存在一些安全风险和架构上的限制,Helm 3 采用了更简单的架构,将相关功能集成到了 Helm 客户端中,直接与 Kubernetes API 服务器进行交互,从而不再需要 Tiller 组件。所以在你基于当前环境安装 Helm 3 并准备安装 KubeSphere 时,无需考虑 Tiller 的安装及版本问题
5)、看到还有很多文档上还使用Tiller去分配权限,上面已经说了,3.X版本及以上不再使用Tiller,kubelet的上下文中已经有了用户,~/.kube/config 文件的具体位置是用户主目录下的 .kube 目录中的 config 文件。
其中 ~ 代表用户主目录,对于大多数 Linux 系统,如果以 root 用户登录,其主目录是 /root,那么 ~/.kube/config 实际路径就是 /root/.kube/config;如果是普通用户(例如 user1),其主目录是 /home/user1,则 ~/.kube/config 实际路径为 /home/user1/.kube/config 。
如果你想给kubernetes-admin分配具体权限。使用现有管理员用户(如 kubernetes-admin),如果你已经有一个具有 cluster-admin 权限的用户(如 kubernetes-admin),可以直接使用它,无需额外配置
#检查当前上下文,确保输出为 kubernetes-admin@kubernetes 或类似的管理员上下文
kubectl config current-context
#直接使用 Helm 3,需要先创建my-chart目录
helm install my-release my-chart/
命令解释:在 Helm 命令中,install my-release my-chart/ 是执行安装 Helm Chart 的核心操作,具体含义如下:
参数解析
install
Helm 的子命令,用于将一个 Chart 部署到 Kubernetes 集群中。
my-release
Release 名称:Helm 为每个部署的 Chart 实例分配的唯一标识符。
用途:
区分同一 Chart 的不同部署(例如,开发环境和生产环境可能使用相同的 Chart,但需要不同的 Release 名称)。
通过 helm upgrade 或 helm uninstall 操作
示例
helm install dev-mysql stable/mysql # 开发环境的 MySQL 实例
helm install prod-mysql stable/mysql # 生产环境的 MySQL 实例
my-chart/
Chart 路径:指向本地文件系统中的 Chart 目录。
要求:
目录必须包含有效的 Chart 结构(如 Chart.yaml、values.yaml、templates/ 目录等)。
可以是相对路径或绝对路径。
八、通过kubectl命令安装OpenEBS存储类
1)、创建新的名称空间
#在kubelet中创建新的名称空间
kubectl create ns openebs
#查看所有的名称空间
kubectl get ns
mkdir /root/k8s/openebs/
cd /root/k8s/openebs/
#下载yaml配置文件
wget https://openebs.github.io/charts/openebs-operator.yaml
kubectl apply -f openebs-operator.yaml

2)、检查 OpenEBS 组件状态、验证存储类
#检查 OpenEBS 组件状态
kubectl get pods -n openebs

需要等待一会,等它容器创建好
#验证存储类
kubectl get sc

openebs-hostpath:使用节点本地目录作为存储(适合测试环境)
openebs-device:使用裸磁盘作为存储(性能更高)
3)、设置默认的StorageClass
#将openebs-hostpath设置为默认的StorageClass
kubectl patch storageclass openebs-hostpath -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
#输出应为 storageclass.storage.k8s.io/openebs-hostpath patched

#再次使用命令查看,openebs-hostpath变成默认存储
kubectl get sc

4)、到这里,差不多已经完成了,前面我们把master节点污点去掉了,现在要把master污点加上,避免其他节点资源跟它抢占
kubectl taint nodes k8s-node1 node-role.kubernetes.io=master:NoSchedule
#应为输出 node/k8s-node1 tainted
前置环境已经安装好了
九、NFS和OpenEBS存储类对比,以及这两个存储类的应用场景

1)、NFS
1、NFS特点
跨节点共享文件,通俗讲:可以把NFS比作共享网盘,所有节点访问同一个存储空间
2、类型
网络文件系统(共享存储)
3、部署位置
独立服务器(物理机/虚拟机)
4、数据访问协议
文件级(POSIX 接口)
2)、OpenEBS
1、OpenEBS特点
为容器提供持久化、可移植的存储;通俗讲:OpenEBS更像给每个Pod分配专属移动硬盘
2、类型
Kubernetes 原生的容器附加存储 (CAS)
3、部署位置
直接运行在 Kubernetes 集群节点上
4、数据访问协议
块级(iSCSI)或文件级(ZFS/NFS Provisioner)
3)、架构对比


4)、关键特性对比

5)、典型使用场景
1、NFS使用场景
-
共享配置文件、静态资源(如图片/视频)
-
开发测试环境
-
需要跨节点共享读写的应用(如 CI/CD 工件仓库)
2、OpenEBS使用场景
-
数据库类应用(MySQL, PostgreSQL, Redis)
- 因块存储提供更低延迟和更高 IOPS
-
有状态服务的多副本部署
- 如 Kafka、Elasticsearch(利用 cStor 跨节点复制)
-
对存储性能敏感的云原生应用
-
避免云厂商锁定的场景(跨公有云/混合云部署)

6)、性能对比(示例)

7)、运维对比

8)、如何选择?
选择 NFS 当:
-
已有 NFS 基础设施
-
需要低成本共享存储
-
应用只需文件级存储(如 Web 静态资源)
选择 OpenEBS 当:
-
运行数据库或有状态服务
-
追求 Kubernetes 原生存储体验
-
需要低延迟本地磁盘性能(LocalPV)
-
避免云厂商托管存储(如 EBS/Azure Disk)的锁定
9)、 互补使用方案

总结

九、安装kubesphere图形化工具(master节点执行)
更多详细操作可以参考下面的官方链接:https://kubesphere.io/zh/docs/v4.1/03-installation-and-upgrade/02-install-kubesphere/05-appendix/
安装kubesphere方式一
0)、安装kubesphere前置条件
参考目录一、二、三、四目录操作一次,操作完,前置环境就准备好了
1)、最小化安装kubesphere,也就是仅安装ks-core
vi heml-install-kubesphere.yaml
# ============== 1. CRD 自动安装配置 ==============
crds:
enabled: true # Helm 自动安装 CRD
# ============== 2. 国内镜像源替换 ==============
images:
# KubeSphere 核心组件镜像(阿里云镜像源)
ks_installer:
repository: registry.cn-beijing.aliyuncs.com/kubesphere/ks-installer
tag: v3.3.0
pullPolicy: IfNotPresent
# 其他依赖组件镜像(按需替换)
kubesphere:
repository: registry.cn-beijing.aliyuncs.com/kubesphere
tag: v3.3.0
etcd:
repository: registry.cn-hangzhou.aliyuncs.com/google_containers/etcd
tag: v3.4.13
mysql:
repository: registry.cn-hangzhou.aliyuncs.com/kubesphere/mysql
tag: 5.7
# ============== 3. KubeSphere 核心配置 ==============
configuration:
# 持久化存储配置
persistence:
storageClass: "" # 填写你的 StorageClass 名称(如 "nfs-storage")
# ETCD 配置
etcd:
monitoring: false
endpointIps: "192.168.10.100,192.168.10.101,192.168.10.102" # 替换为你的 ETCD 节点 IP
port: 2379
tlsEnable: true
# 基础组件资源配置
common:
mysqlVolumeSize: 20Gi
minioVolumeSize: 20Gi
etcdVolumeSize: 20Gi
redisVolumSize: 2Gi
# 监控组件配置
monitoring:
prometheusReplicas: 1
prometheusMemoryRequest: 400Mi
prometheusVolumeSize: 20Gi
grafana:
enabled: true # 禁用 Grafana(国内镜像可自行开启)
# 日志组件配置
logging:
enabled: false # 禁用 ELK(国内镜像可自行开启)
elasticsearchMasterReplicas: 1
elasticsearchDataReplicas: 1
logsidecarReplicas: 2
elasticsearchMasterVolumeSize: 4Gi
elasticsearchDataVolumeSize: 20Gi
# DevOps 配置
devops:
enabled: true #这个必须要开启,因为devops已经内嵌了jekins以及整合了jekins的CI/CD流水线发布功能
jenkinsMemoryLim: 2Gi
jenkinsMemoryReq: 1000Mi
jenkinsJavaOpts_Xms: 512m
jenkinsJavaOpts_Xmx: 512m
jenkinsJavaOpts_MaxRAM: 2g
jenkinsVolumeSize: 8Gi
sonarqube:
enabled: true
postgresqlVolumeSize: 8Gi
# 其他功能开关
servicemesh:
enabled: false
notification:
enabled: true
alerting:
enabled: true
# ============== 4. 网络配置(按需修改) ==============
network:
kubePodsCIDR: "10.233.64.0/18"
kubeServiceCIDR: "10.233.0.0/18"
2)、如果你电脑之前安装过kubesphere,但是安装失败了,换成Helm安装kubesphere,要先删除kubelet-system命名空间
kubectl delete ns kubesphere-system
#多删除几次,直到输出No resources found
3)、创建命名空间,开始安装kubesphere
#再创建命名空间
kubectl create ns kubesphere-system
#开始下载CRD以及安装kubesphere
helm install kubesphere kubesphere/ks-core --namespace kubesphere-system --create-namespace --values heml-install-kubesphere.yaml --replace
出现下面这地址,就表示安装成功了
Please be patient and wait for several seconds for the KubeSphere deployment to complete.
1. Wait for Deployment Completion
Confirm that all KubeSphere components are running by executing the following command:
kubectl get pods -n kubesphere-system
2. Access the KubeSphere Console
Once the deployment is complete, you can access the KubeSphere console using the following URL:
http://192.168.10.100:30880
3. Login to KubeSphere Console
Use the following credentials to log in:
Account: admin
Password: P@88w0rd

如果出现上面地址,在浏览器访问失败,不要慌,看看组件运行状态,可能是组件还没完全运行起来
#查看组件运行状态
kubectl get pods -n kubesphere-system -w

或者使用命令查看kubesphere的安装日志
kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l app=ks-install -o jsonpath='{.items[0].metadata.name}') -f
我这边全都运行起来了,再去访问一下浏览器,输入控制台答应的账号密码后账号:admin密码:P@88w0rd
要查看集群节点,需要点host才会进入所有节点页面,以及其它配置项
新版kubesphere和旧版本2.Xkubesphere控制台页面差别还是挺大的,下面展示一下旧版的控制台页面,旧版本中,如果需要重新选装一些组件,需要在ks-installer中去选择开启的组件。而新版中,有两种方式,一种使用命令行,下面有介绍;另外一种则是通过控制台页面,左上角的扩展市场去选择安装什么组件
4)、如果想查看Jenkins账号密码(kubesphere将Jenkins内嵌了)
4-1)、获取jekins的账号密码
kubectl -n kubesphere-devops-system get secret devops-jenkins -o yaml
#输出中,可以看到账号和密码都用base64加密了
#data:
# jenkins-admin-password: d0lUQ0JUMlNaQ1JObVNRSFFLMm9iOQ==
# jenkins-admin-token: MTE3OTczMzk2MzMxODkzNzk2MTUzMDg2MjI4MjU2NjIzNQ==
# jenkins-admin-user: YWRtaW4=
#kind: Secret
#metadata:
# annotations:
# meta.helm.sh/release-name: devops
# meta.helm.sh/release-namespace: kubesphere-devops-system
# creationTimestamp: "2025-05-26T12:45:06Z"
# labels:
# app.kubernetes.io/instance: devops
# app.kubernetes.io/managed-by: Helm
# app.kubernetes.io/name: devops-extension
# app.kubernetes.io/version: v4.1.3
# devops.kubesphere.io/component: Jenkins
# helm.sh/chart: extension-1.1.3
# heritage: Helm
# kubesphere.io/extension-ref: devops
# name: devops-jenkins
# namespace: kubesphere-devops-system
# resourceVersion: "220082"
# uid: 4f9fa29a-d6f9-421e-9b9c-462b2bf34dbc
#type: Opaque

4-2)、将使用base64加密后的账号密码解密
JENKINS_ADMIN_USER=$(kubectl get secret devops-jenkins -n kubesphere-devops-system -o jsonpath="{.data.jenkins-admin-user}" | base64 -d)
JENKINS_ADMIN_PASSWORD=$(kubectl get secret devops-jenkins -n kubesphere-devops-system -o jsonpath="{.data.jenkins-admin-password}" | base64 -d)
echo "用户名: $JENKINS_ADMIN_USER,密码: $JENKINS_ADMIN_PASSWORD"
#输出 用户名: admin,密码: wITCBT2SZCRNmSQHQK2ob9

安装kubesphere方式二(这个安装方式是完整版的kubesphere,开启所有的功能组件)
硬件要求:
0)、安装kubesphere前置条件
参考目录一、二、三、四目录操作一次,操作完,前置环境就准备好了
1)、下载kubesphere-installer和cluster-configuration
wget https://github.com/kubesphere/ks-installer/releases/download/v3.4.1/kubesphere-installer.yaml
wget https://github.com/kubesphere/ks-installer/releases/download/v3.4.1/cluster-configuration.yaml

如果下载不下来,可以从我的网盘中下载,里面的cluster-configuration.yaml是已经修改好了的,你们使用只需要修改etcd监控指标这一项中有个IP,修改成你们master节点IP就可以了,然后直接使用命令安装kubespherekubectl apply -f kubesphere-installer-v3.1.1.yaml kubectl apply -f cluster-configuration-v3.1.1.yaml将这两个yaml文件进行安装部署,第二步就可以跳过了
通过网盘分享的文件:3.X版本kubesphere安装所需的yaml文件
链接: https://pan.baidu.com/s/1EoDTSNSEpuZfVwGkK0Fgog?pwd=bgt3
提取码: bgt3
2)、修改集群配置文件的cluster-configuration.yaml
在 cluster-configuration.yaml中指定我们需要开启的功能,参照官网“启用可插拔组件”
https://kubesphere.io/zh/docs/v3.4/pluggable-components/
vim cluster-configuration.yaml
#开启etcd监控指标、redis等功能;需要开启的功能都用红框标注,开启etcd的监控指标,下面还有个IP配置,这个要配置你的master节点IP



然后退出并保存
3)、开始安装kubesphere-installer.yaml和cluster-configuration
#先安装kubesphere-installer.yaml
kubectl apply -f kubesphere-installer.yaml
#安装集群配置
kubectl apply -f cluster-configuration.yaml
4)、检查安装日志
kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l 'app in (ks-install, ks-installer)' -o jsonpath='{.items[0].metadata.name}') -f

打印出这个表示已经安装好了,直接浏览器输入打印的ip地址,然后输入账号密码就可以访问kubesphere控制台页面了。30880端口不需要再配置防火墙了,因为前面在云服务配置中已经配置了一个端口区间,使用任意机器的ip:30880就可以访问kubesphere控制台页面。账号:admin密码:P@88w0rd
如果发现过去很久,还有很多Pod状态不是Running的,需要查看一下,是不是出问题了
kubectl describe pod -n <名称空间> <Podname>
kubectl describe pod -n kubesphere-monitoring-system alertmanager-main-1
只要是pulling images就表示没问题,正在下载镜像
5)、解决etcd监控证书找不到问题
前面在集群配置的yaml文件中开启了etcd指标监控,这是需要etcd的证书,报错信息如下
kubectl describe pod -n kubesphere-monitoring-system prometheus-k8s-0
报错信息如下:
kube-etcd-client-certs not found

解决方案执行以下命令:
kubectl -n kubesphere-monitoring-system create secret generic kube-etcd-client-certs --from-file=etcd-client-ca.crt=/etc/kubernetes/pki/etcd/ca.crt --from-file=etcd-client.crt=/etc/kubernetes/pki/apiserver-etcd-client.crt --from-file=etcd-client.key=/etc/kubernetes/pki/apiserver-etcd-client.key

然后继续等待,大概5分钟左右,所有的pod全部都是Running状态了
单节点使用kubekey一站式安装k8s、kubesphere,方式三
注意,这个是没有安装前置条件,这个方式三是在一台机器上部署所有东西docker、kubernetes、kubesphere
0)、这种安装方式除了修改hostname外(当然你要是不想改也行),就没有前置条件前置条件,kk会自动安装一系列所有的东西,包括docker、k8s、kubesphere
1)、硬件要求
Centos7:2核CPU,4GB内存,40GB磁盘空间
2)、准备kubekey
export KKZONE=cn
curl -sfL https://get-kk.kubesphere.io | VERSION=v1.1.1 sh -

这个绿色的kk就是可执行文件
#修改kk的权限,如果kk是绿色的,可以不用执行这个命令
chmod +x kk
3)、使用kubekey引导安装docker、k8s、kubesphere
系统非常纯净,连docker都没有安装的情况下,kubekey会将docker、k8s、kubesphere一起安装。安装顺序是先安装docker-->k8s----->kubesphere
yum install -y conntrack
./kk create cluster --with-kubernetes v1.20.4 --with-kubesphere v3.1.1

正在安装中,可以在开一个窗口,看看安装情况
kubectl get pod -A
可以看到pod正在创建中
大概十几分钟后,控制台就打印出这个,已经安装好了
确认所有的pod都是运行中状态,就可以通过浏览器访问kubesphere控制台。通过这种kk方式部署的,发现会很少东西,kk安装方式默认就是最小化安装的账号:admin密码:P@88w0rd
4)、安装后开启某些功能

1.在kubesphere控制台页面,找到自定义资源,搜索clusterconfiguration
点击这个clusterconfiguration
2.编辑这个clusterconfiguration文件
3.想要开启什么功能,可以将这个false改成true
集群部署使用kubekey一站式安装k8s、kubesphere,方式四
注意:这种方式也是没有前置条件的,方式四安装是多节点的,针对k8s集群的简单安装方式
1)、准备kubekey
export KKZONE=cn
curl -sfL https://get-kk.kubesphere.io | VERSION=v1.1.1 sh -

这个绿色的kk就是可执行文件
#修改kk的权限,如果kk是绿色的,可以不用执行这个命令
chmod +x kk
2)、创建集群
./kk create config --with-kubernetes v1.20.4 --with-kubesphere v3.1.1

3)、编辑下载的config-sample.yaml文件
vim config-sample.yaml
注意,需要修改的就只有这两个框的内容,第一个框:你有多少个节点,填多少个,有四个或者更多,就继续复制- {name}然后修改ip。第二个地方就是哪个节点是etcd、master,如果想做多主多从,master:这个配置继续复制粘贴就好了,哪几个节点当woker从节点,就配置对应的hostname,继续往下看会有ClusterConfiguration,这个是集群配置,想开启什么功能,就将false改为true,机器配置不高,可以不用开启其它配置了。然后退出并且保存
下面给出yaml文件的全部内容
vim config-sample.yaml
apiVersion: kubekey.kubesphere.io/v1alpha1
kind: Cluster
metadata:
name: sample
spec:
hosts:
- {name: k8s-node1, address: 192.168.10.100, internalAddress: 192.168.10.100, user: root, password: root}
- {name: k8s-node2, address: 192.168.10.101, internalAddress: 192.168.10.101, user: root, password: root}
- {name: k8s-node3, address: 192.168.10.102, internalAddress: 192.168.10.102, user: root, password: root}
roleGroups:
etcd:
- k8s-node1
master:
- k8s-node1
worker:
- k8s-node2
- k8s-node3
controlPlaneEndpoint:
domain: lb.kubesphere.local
address: ""
port: 6443
kubernetes:
version: v1.20.4
imageRepo: kubesphere
clusterName: cluster.local
network:
plugin: calico
kubePodsCIDR: 10.233.64.0/18
kubeServiceCIDR: 10.233.0.0/18
registry:
registryMirrors: []
insecureRegistries: []
addons: []
---
apiVersion: installer.kubesphere.io/v1alpha1
kind: ClusterConfiguration
metadata:
name: ks-installer
namespace: kubesphere-system
labels:
version: v3.1.1
spec:
persistence:
storageClass: ""
authentication:
jwtSecret: ""
zone: ""
local_registry: ""
etcd:
monitoring: false
endpointIps: localhost
port: 2379
tlsEnable: true
common:
redis:
enabled: false
redisVolumSize: 2Gi
openldap:
enabled: false
openldapVolumeSize: 2Gi
minioVolumeSize: 20Gi
monitoring:
endpoint: http://prometheus-operated.kubesphere-monitoring-system.svc:9090
es:
elasticsearchMasterVolumeSize: 4Gi
elasticsearchDataVolumeSize: 20Gi
logMaxAge: 7
elkPrefix: logstash
basicAuth:
enabled: false
username: ""
password: ""
externalElasticsearchUrl: ""
externalElasticsearchPort: ""
console:
enableMultiLogin: true
port: 30880
alerting:
enabled: false
# thanosruler:
# replicas: 1
# resources: {}
auditing:
enabled: false
devops:
enabled: false
jenkinsMemoryLim: 2Gi
jenkinsMemoryReq: 1500Mi
jenkinsVolumeSize: 8Gi
jenkinsJavaOpts_Xms: 512m
jenkinsJavaOpts_Xmx: 512m
jenkinsJavaOpts_MaxRAM: 2g
events:
enabled: false
ruler:
enabled: true
replicas: 2
logging:
enabled: false
logsidecar:
enabled: true
replicas: 2
metrics_server:
enabled: false
monitoring:
storageClass: ""
prometheusMemoryRequest: 400Mi
prometheusVolumeSize: 20Gi
multicluster:
clusterRole: none
network:
networkpolicy:
enabled: false
ippool:
type: none
topology:
type: none
openpitrix:
store:
enabled: false
servicemesh:
enabled: false
kubeedge:
enabled: false
cloudCore:
nodeSelector: {"node-role.kubernetes.io/worker": ""}
tolerations: []
cloudhubPort: "10000"
cloudhubQuicPort: "10001"
cloudhubHttpsPort: "10002"
cloudstreamPort: "10003"
tunnelPort: "10004"
cloudHub:
advertiseAddress:
- ""
nodeLimit: "100"
service:
cloudhubNodePort: "30000"
cloudhubQuicNodePort: "30001"
cloudhubHttpsNodePort: "30002"
cloudstreamNodePort: "30003"
tunnelNodePort: "30004"
edgeWatcher:
nodeSelector: {"node-role.kubernetes.io/worker": ""}
tolerations: []
edgeWatcherAgent:
nodeSelector: {"node-role.kubernetes.io/worker": ""}
tolerations: []
4)、使用kubekey引导安装集群
系统非常纯净,连docker都没有安装的情况下,kubekey会将docker、k8s、kubesphere一起安装。安装顺序是先安装docker-->k8s----->kubesphere
#所有节点都要执行
yum install -y conntrack
#kk使用配置文件安装docker、k8s、kubesphere
./kk create cluster -f config-sample.yaml
出现这个表示安装完成
注意:要等待所有的pod都是运行中状态
kubectl get pod -A
5)、验证安装
1、云服务的组内互相通信要打开

2、将k8s的区间端口暴露


3、访问任意节点IP:30880,进入kubesphere控制台页面

账号:admin密码:P@88w0rd
十、kubesphere多租户
1)、多租户角色关系介绍图

2)、创建用户管理员账号
1、进入访问控制

十一、Ingress安装
1)、Ingress的概念
Ingress概念(统一网关入口):Service的统一网关入口;而service是统一管理所有的pod,例如,将三台机器上的nginx交由service统一管理,当nginx扩容或者缩容IP地址发生变化这样就不需要去修改前端地址,因为service是统一管理所有的80端口。ingress底层其实就是一个nginx

2)、下载Ingress的yaml文件
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml
# 修改镜像地址
vi deploy.yaml
#将images-的值改为如下值:
registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/ingress-nginx-controller:v0.46.0
#检查安装的结果
kubectl get pod,svc -n ingress-nginx
#最后别忘记把svc暴露的端口要放行
如果通过wget下载不到yaml文件,也可以直接使用下面的yaml文件无需修改直接拷贝使用
vi ingress-deploy.yaml
apiVersion: v1
kind: Namespace
metadata:
name: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
---
# Source: ingress-nginx/templates/controller-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx
namespace: ingress-nginx
automountServiceAccountToken: true
---
# Source: ingress-nginx/templates/controller-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx-controller
namespace: ingress-nginx
data:
---
# Source: ingress-nginx/templates/clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
name: ingress-nginx
rules:
- apiGroups:
- ''
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
verbs:
- list
- watch
- apiGroups:
- ''
resources:
- nodes
verbs:
- get
- apiGroups:
- ''
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- extensions
- networking.k8s.io # k8s 1.14+
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ''
resources:
- events
verbs:
- create
- patch
- apiGroups:
- extensions
- networking.k8s.io # k8s 1.14+
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- networking.k8s.io # k8s 1.14+
resources:
- ingressclasses
verbs:
- get
- list
- watch
---
# Source: ingress-nginx/templates/clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
name: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ingress-nginx
subjects:
- kind: ServiceAccount
name: ingress-nginx
namespace: ingress-nginx
---
# Source: ingress-nginx/templates/controller-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx
namespace: ingress-nginx
rules:
- apiGroups:
- ''
resources:
- namespaces
verbs:
- get
- apiGroups:
- ''
resources:
- configmaps
- pods
- secrets
- endpoints
verbs:
- get
- list
- watch
- apiGroups:
- ''
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- extensions
- networking.k8s.io # k8s 1.14+
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- extensions
- networking.k8s.io # k8s 1.14+
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- networking.k8s.io # k8s 1.14+
resources:
- ingressclasses
verbs:
- get
- list
- watch
- apiGroups:
- ''
resources:
- configmaps
resourceNames:
- ingress-controller-leader-nginx
verbs:
- get
- update
- apiGroups:
- ''
resources:
- configmaps
verbs:
- create
- apiGroups:
- ''
resources:
- events
verbs:
- create
- patch
---
# Source: ingress-nginx/templates/controller-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx
namespace: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: ingress-nginx
subjects:
- kind: ServiceAccount
name: ingress-nginx
namespace: ingress-nginx
---
# Source: ingress-nginx/templates/controller-service-webhook.yaml
apiVersion: v1
kind: Service
metadata:
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx-controller-admission
namespace: ingress-nginx
spec:
type: ClusterIP
ports:
- name: https-webhook
port: 443
targetPort: webhook
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
---
# Source: ingress-nginx/templates/controller-service.yaml
apiVersion: v1
kind: Service
metadata:
annotations:
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
- name: https
port: 443
protocol: TCP
targetPort: https
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
---
# Source: ingress-nginx/templates/controller-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
revisionHistoryLimit: 10
minReadySeconds: 0
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
spec:
dnsPolicy: ClusterFirst
containers:
- name: controller
image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/ingress-nginx-controller:v0.46.0
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
exec:
command:
- /wait-shutdown
args:
- /nginx-ingress-controller
- --election-id=ingress-controller-leader
- --ingress-class=nginx
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
- --validating-webhook=:8443
- --validating-webhook-certificate=/usr/local/certificates/cert
- --validating-webhook-key=/usr/local/certificates/key
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
runAsUser: 101
allowPrivilegeEscalation: true
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: LD_PRELOAD
value: /usr/local/lib/libmimalloc.so
livenessProbe:
failureThreshold: 5
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
ports:
- name: http
containerPort: 80
protocol: TCP
- name: https
containerPort: 443
protocol: TCP
- name: webhook
containerPort: 8443
protocol: TCP
volumeMounts:
- name: webhook-cert
mountPath: /usr/local/certificates/
readOnly: true
resources:
requests:
cpu: 100m
memory: 90Mi
nodeSelector:
kubernetes.io/os: linux
serviceAccountName: ingress-nginx
terminationGracePeriodSeconds: 300
volumes:
- name: webhook-cert
secret:
secretName: ingress-nginx-admission
---
# Source: ingress-nginx/templates/admission-webhooks/validating-webhook.yaml
# before changing this value, check the required kubernetes version
# https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#prerequisites
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: admission-webhook
name: ingress-nginx-admission
webhooks:
- name: validate.nginx.ingress.kubernetes.io
matchPolicy: Equivalent
rules:
- apiGroups:
- networking.k8s.io
apiVersions:
- v1beta1
operations:
- CREATE
- UPDATE
resources:
- ingresses
failurePolicy: Fail
sideEffects: None
admissionReviewVersions:
- v1
- v1beta1
clientConfig:
service:
namespace: ingress-nginx
name: ingress-nginx-controller-admission
path: /networking/v1beta1/ingresses
---
# Source: ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: ingress-nginx-admission
annotations:
helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: admission-webhook
namespace: ingress-nginx
---
# Source: ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ingress-nginx-admission
annotations:
helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: admission-webhook
rules:
- apiGroups:
- admissionregistration.k8s.io
resources:
- validatingwebhookconfigurations
verbs:
- get
- update
---
# Source: ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ingress-nginx-admission
annotations:
helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: admission-webhook
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ingress-nginx-admission
subjects:
- kind: ServiceAccount
name: ingress-nginx-admission
namespace: ingress-nginx
---
# Source: ingress-nginx/templates/admission-webhooks/job-patch/role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: ingress-nginx-admission
annotations:
helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: admission-webhook
namespace: ingress-nginx
rules:
- apiGroups:
- ''
resources:
- secrets
verbs:
- get
- create
---
# Source: ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: ingress-nginx-admission
annotations:
helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: admission-webhook
namespace: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: ingress-nginx-admission
subjects:
- kind: ServiceAccount
name: ingress-nginx-admission
namespace: ingress-nginx
---
# Source: ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: ingress-nginx-admission-create
annotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: admission-webhook
namespace: ingress-nginx
spec:
template:
metadata:
name: ingress-nginx-admission-create
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: admission-webhook
spec:
containers:
- name: create
image: docker.io/jettech/kube-webhook-certgen:v1.5.1
imagePullPolicy: IfNotPresent
args:
- create
- --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc
- --namespace=$(POD_NAMESPACE)
- --secret-name=ingress-nginx-admission
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
restartPolicy: OnFailure
serviceAccountName: ingress-nginx-admission
securityContext:
runAsNonRoot: true
runAsUser: 2000
---
# Source: ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: ingress-nginx-admission-patch
annotations:
helm.sh/hook: post-install,post-upgrade
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: admission-webhook
namespace: ingress-nginx
spec:
template:
metadata:
name: ingress-nginx-admission-patch
labels:
helm.sh/chart: ingress-nginx-3.33.0
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.47.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: admission-webhook
spec:
containers:
- name: patch
image: docker.io/jettech/kube-webhook-certgen:v1.5.1
imagePullPolicy: IfNotPresent
args:
- patch
- --webhook-name=ingress-nginx-admission
- --namespace=$(POD_NAMESPACE)
- --patch-mutating=false
- --secret-name=ingress-nginx-admission
- --patch-failure-policy=Fail
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
restartPolicy: OnFailure
serviceAccountName: ingress-nginx-admission
securityContext:
runAsNonRoot: true
runAsUser: 2000
3)、使用kubectl apply 安装ingress
kubectl apply -f ingress-deploy.yaml

kubectl get svc -A
可以看到,type是NodePort,ingress-nginx暴漏了两个端口,一个30925,一个32299。30925是http请求暴露的端口,32299是https暴露的端口,NodePort会在所有的节点都暴露这两个端口
4)、准备一个测试文件,测试ingress的转发

vi test.yaml
#直接拷贝使用
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-server
spec:
replicas: 2
selector:
matchLabels:
app: hello-server
template:
metadata:
labels:
app: hello-server
spec:
containers:
- name: hello-server
image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/hello-server
ports:
- containerPort: 9000
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-demo
name: nginx-demo
spec:
replicas: 2
selector:
matchLabels:
app: nginx-demo
template:
metadata:
labels:
app: nginx-demo
spec:
containers:
- image: nginx
name: nginx
---
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-demo
name: nginx-demo
spec:
selector:
app: nginx-demo
ports:
- port: 8000
protocol: TCP
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
labels:
app: hello-server
name: hello-server
spec:
selector:
app: hello-server
ports:
- port: 8000
protocol: TCP
targetPort: 9000
kubectl apply -f test.yaml

kubectl get pods -A
可以看到,创建了两个副本为nginx-demo、hello-server的pod

直接使用curl测试nginx-demo的service
kubectl get svc -A
输出nginx-demo和hello-server的service
curl 10.96.157.177:8000
可以看到返回了nginx的首页
1)、添加路由规则。使用域名请求,通过不同的域名请求由ingress转发到相对应的service,比如hello-server或者nginx-demo
准备一个ingress转发规则的yaml文件
vi ingress-rule.yaml
#直接拷贝使用
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
#这个name名字随便取,只要跟别的名字不重复就行了
name: ingress-host-bar
spec:
ingressClassName: nginx
rules:
#- host:表示域名匹配规则,如果是hello.atguigu转发到hello-server
- host: "hello.atguigu.com"
http:
paths:
#pathType: Prefix 表示前缀模式
- pathType: Prefix
#path:以/开始的请求
path: "/"
#backend:后台服务
backend:
service:
name: hello-server
port:
# hello-server的端口8000
number: 8000
- host: "demo.atguigu.com"
http:
paths:
- pathType: Prefix
# 如果请求的域名是demo.atguigu.com并且是/nginx,
#则就会把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404,
#可以在静态资源文件创建一个名为nginx文件,然后在浏览器使用demo.atguigu.com/nginx就会下载下载这个资源文件
path: "/nginx"
backend:
service:
name: nginx-demo ## java,比如使用路径重写,去掉前缀nginx
port:
number: 8000
应用ingress路由规则
kubectl apply -f ingress-rule.yaml
#如果已经应用了这个yaml文件,后面想要修改yaml文件的内容,可以使用下面命令,如果是文件不在默认名称空间,命令后面要加-n <名称空间>
kubectl edit ing ingress-rule.yaml

1)、查看ingress有多少路由规则
kubectl get ingress

2)、在windows的hots文件添加域名映射关系
注意:这里的IP应该是k8s给ingress分配的IP

3)、在浏览器使用域名访问hello-server
流程:浏览器向k8s的ingress发送http请求,根据ingress路由规则匹配转发到哪个service上
2)、ingress其它规则:路径重写规则
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: ingress-host-bar
spec:
ingressClassName: nginx
rules:
- host: "hello.atguigu.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: hello-server
port:
number: 8000
- host: "demo.atguigu.com"
http:
paths:
- pathType: Prefix
path: "/nginx(/|$)(.*)" # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
backend:
service:
name: nginx-demo ## java,比如使用路径重写,去掉前缀nginx
port:
number: 8000
3)、ingress其它规则:流量限制
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-limit-rate
annotations:
nginx.ingress.kubernetes.io/limit-rps: "1"
spec:
ingressClassName: nginx
rules:
- host: "haha.atguigu.com"
http:
paths:
- pathType: Exact
path: "/"
backend:
service:
name: nginx-demo
port:
number: 8000
十二、kubesphere部署mysql应用
1、kubesphere添加阿里云私有镜像仓库密钥
私有仓库可以使用阿里云的,也可以使用harbor自己搭建一个私有仓库,因为dockerhub被强了,在kubesphere中直接搜索mysql等镜像,是搜不到的

注意:这里添加的阿里云镜像仓库地址,HTTPS://<阿里云镜像仓库地址>/这个<阿里云镜像仓库地址>是带有名称空间的,要从阿里云的仓库基本信息中有个docker命令----Registry中拉取镜像取马赛克那部分

2、给mysql在配置中心创建配置



key:my.cnf
mysql配置示例
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
init_connect='SET collation_connection = utf8mb4_unicode_ci'
init_connect='SET NAMES utf8mb4'
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
skip-character-set-client-handshake
skip-name-resolve

3、给mysql创建pvc挂载
给mysql创建pvc挂载作用是用于存储mysql的数据
选择单节点读写,一般有状态服务都是选择单节点读写,无状态应用是使用多节点读写;测试使用,内存就给5G

4、进入工作负载,开始创建mysql应用
部署应用,要先进入企业空间的某个项目里面
部署的三个状态解释:
- 部署:
- 开发的微服务程序,可以使用这个部署状态,微服务是无状态应用。
- 有状态副本集:
- 部署中间件,比如mysql、redis、mq,这种中间件需要有状态应用,它的数据存在别的地方,如果某个中间件器挂了,在别的机器重新拉起了中间件,它的数据应该还是存在的。
- 守护进程集:
- 假设集群里面有五台机器,想要做一个日志收集工作,收集每一台机器上的日志,所以需要在每一个机器运行日志收集器。
不管是部署、还是有状态副本集、守护进程集最终都是部署成一个个的pod,运行在容器组中,也就是工作负载下面有个容器组


注意:我这里使用的私有镜像仓库,因为dockerhub被墙了,使用dockerbub无法搜索镜像了,前面章节有介绍怎么创建阿里云的私有镜像仓库
注意:不要配置预留,这个pod预留,那个pod配置预留,最后会导致服务器空间就不够了


mysql的所有数据都是在这个目录下的/var/lib/mysql,所以要将这个目录的数据挂载出去,挂载到前面创建的pvc中

这里配置的my.cnf就是前面创建的mysql配置文件,将mysql内部目录/etc/mysql/conf.d下需要一个cnf的配置文件,将所需要的配置文件使用挂载方式使用外部的my.cnf



5、进入mysql容器内部



十三、如果后期想要启用某些配置,比如启用monitoring,我第一次安装的时候,那个yaml配置的monitoring是没有开启的,现在要开启它
1)、修改配置后的更新流程,更新 values.yaml 文件
(1)更新 values.yaml 文件
编辑您的 values.yaml,启用需要的功能(例如开启 monitoring或 logging),将false改为true
monitoring:
enabled: true # 从 false 改为 true
logging:
enabled: true # 从 false 改为 true
2)、执行 Helm 升级命令
helm upgrade kubesphere kubesphere/ks-core \
--namespace kubesphere-system \
--values values.yaml \
--reuse-values # 保留未修改的原有配置
关键参数说明:
–reuse-values:保留之前安装时设置的未在本次 values.yaml 中覆盖的值。
如果某些配置需要强制重置,可以去掉 --reuse-values。
3)、验证更新状态
# 查看 ks-installer Pod 的日志
kubectl logs -n kubesphere-system \
$(kubectl get pod -n kubesphere-system -l app=ks-install -o jsonpath='{.items[0].metadata.name}') \
-f
# 检查新组件的 Pod 状态(例如 servicemesh)
kubectl get pod -n kubesphere-service-mesh-system
十四、生产环境做更新升级(都必须重新搞一个跟生产环境一模一样的环境来做下测试),需要注意几个方面:
1)、生产环境低风险推荐升级流程
步骤 1:预升级检查
# 检查当前 Helm 发布状态
helm get values kubesphere -n kubesphere-system --all > current-values.yaml
# 检查集群健康状态
kubectl get nodes
kubectl get pod -A | grep -v Running
步骤 2:执行差异化升级(推荐)
# 仅应用本次修改的配置(避免意外覆盖其他值)
helm upgrade kubesphere kubesphere/ks-core \
--namespace kubesphere-system \
--values values.yaml \
--reset-values # 明确要求 Helm 仅使用 values.yaml 中的值(忽略历史配置)
为什么用 --reset-values 而不是 --reuse-values?
生产环境中避免配置漂移(例如有人曾经通过 --set 临时修改过参数),确保升级后的状态完全由版本控制的 values.yaml 定义。
步骤 3:灰度观察
# 观察 ks-installer 日志(关键!)
kubectl logs -n kubesphere-system \
$(kubectl get pod -n kubesphere-system -l app=ks-install -o name) \
--tail=100 -f
# 按组件验证
watch kubectl get pod -n kubesphere-monitoring-system # 如果启用了监控
watch kubectl get pod -n kubesphere-devops-system # 如果启用了 DevOps
步骤 4:回滚准备(必须!)
# 查看历史版本
helm history kubesphere -n kubesphere-system
# 回滚命令(如果需要)
helm rollback kubesphere <REVISION> -n kubesphere-system
2)、生产环境高风险变更的特殊处理
案例 1:修改存储类
persistence:
storageClass: "new-nfs-storage" # 旧值为 "old-nfs-storage"
操作建议:
手动迁移原有 PVC/PV 到新存储类
分两步升级:
# 第一步:先禁用依赖存储的组件
helm upgrade kubesphere --set monitoring.enabled=false,logging.enabled=false
# 第二步:修改存储类后重新启用
helm upgrade kubesphere --values values.yaml
案例 2:启用 ServiceMesh
servicemesh:
enabled: true
操作建议:
先在非生产环境测试 Istio 与现有服务的兼容性
使用 istioctl analyze 预检查:
istioctl analyze -n kubesphere-service-mesh-system
十五、k8s相关重点命令
pod和容器的概念:容器是docker的,一个应用就是一个容器;而一个pod里面可以有多个容器,比如在一个pod里面部署nginx容器以及tomcat容器
0、容器正在创建状态,查看容器详细描述
kubectl describe pod <podname>
#输出内容在最后面有个EVENT事件,这里会详细描诉失败原因
1、对于已经部署了的应用查看部署使用的yaml文件
无论是使用yaml方式部署还是在kubesphere界面部署,都可以使用这个命令
kubectl get pod his-redis-0 -n his -o yaml
2、使用yaml文件部署应用或者删除应用
#根据某个yaml部署
kubectl apply -f xxx.yaml
#删除这个yaml的部署
kubectl delete -f xxx.yaml
3、查看所有pods详细
#输出pod名称,pod中有多少个容器,运行状态,k8s分配的ip,pod所在的节点
kubectl get pods -owide
4、linux系统每秒输出一次容器安装状态
watch -n 1 kubectl get pod
5、查看某个pod的运行日志
kubectl logs <podname>
6、Deployment部署pod的扩容和缩容
# 比如原nginx的副本数是3份,这个命令会扩容到5
# kubectl scale deploy/<podname,不要pod名后面的随机数,比如nginx-5b889fhjhj,podname只取nginx就行> --replicas=5
kubectl scale deploy/nginx --replicas=5
#或者给别的名称空间扩缩容(default名称空间)
kubectl scale -n default deploy/nginx --replicas=5
#缩容,将5份副本缩容到3份
kubectl scale deploy/nginx --replicas=3
7、Deployment部署,自愈&故障转移
如果只是pod中某个容器挂掉了,比如nginx停了,k8s会自动重新启动nginx,使用kubectl get pods 就可以看到后面有个重启次数;如果是机器宕机了,大概5分钟的阈值,k8s就会在其它节点部署容器以达到要求的副本数,比如nginx有三个副本,在三台机器上,其中一起机器宕机了,那么k8s会在其它节点再重新部署一个nginx的pod
1、演示Deployment部署的自愈能力
# 清除所有Pod,比较下面两个命令有何不同效果?
kubectl run mynginx --image=nginx
发现这个mynginx被完全删除了
#演示使用deployment方式部署的,被删除后的效果
kubectl create deployment mytomcat --image=tomcat:8.5.68
可以看到,被删除后立马又重新拉起了一份tomcat
那么要如何完全的删除这个tomcat呢?
#必须使用删除deploy才能完全删除这个pod
#查看deploy
kubectl get deploy
#删除deploy
kubectl delete deploy mytomcat

2、演示Deployment部署,故障转移能力
#查看pod都运行在哪些机器上
kubectl get pod -owide
#在master节点,一直监控my-dep这些pod的状态
#watch -n 1 这个命令是linux自带的,后面跟着命令,表示一秒钟输出一次后面指令的内容,
#也就是一秒钟输出一次kubectl get pod
#也可以让linux一秒钟输出一次docker的运行容器,比如:watch -n 1 docker ps
watch -n 1 kubectl get pod
发现my-dep这三个pod都运行在k8s-node2机器上,现在直接把k8s-node2机器关机,然后等待五分钟看结果。

可以看到,k8s-node2机器关机后,五分钟后,k8s集群在k8s-node3机器上拉起了k8s-node2机器上的所有的pod
8、滚动更新(不停机更新):Deployment
描述:如果有一个应用需要升级,比如原先是v1版本,需要升级到v2版本,黑色箭头代表是目前有流量进来,将一个pod杀死,然后启动新版本,新版本启动成功后再继续杀死一个老版本的pod,启动新版本
# kubectl set deploy/<podname> image <容器名>=<镜像名>:<镜像版本> --record
# --record表示记录这一次版本的更新
kubectl set deploy/my-dep image nginx=nginx:1.61.1 --record
输出:
#使用kubectl自带的监控pod状态命令
kubectl get pod -w
可以看到,原来旧版本的容器还是依然存在,新版本的容器正在创建中
可以看到,起一个新的,就杀死一个旧的(status状态中的Terminating)
9、版本回退
查看某个pod部署过的所有版本记录
# kubectl rollout history deployment/<podname>
kubectl rollout history deployment/my-dep

回滚某个pod
#通过上面图片可以看到,回滚到1版本,1版本的nginx当时部署的时候是拉取的最新版本,而且这个回滚命令的也是滚动更新的
kubectl rollout undo deploy/my-dep --to-revision=1

10、暴漏端口,让service统一管理所有节点上的nginx,前端vue项目不会直接去请求节点上的nginx,因为nginx扩容或者缩容了,前端项目就得更换地址,所以由前端去请求service的地址,由service统一管理nginx
service的概念:管理一组pod的就表示service(也叫服务)
#给前端配置一个公共的地址,也就是service
# kubectl expose deploy <podname> --port=8000 target-port=80
kubectl expose deploy my-dep --port=8000 target-port=80
#命令解释
#expose:暴漏
#--port:表示暴漏的服务端口
#target-port:表示要暴漏服务它的目标端口
#所以后续即便nginx扩容或者缩容,都不需要修改什么地方了,因为这个暴漏的service已经管理了所有nginx,因为nginx的端口就是80
使用命令查看k8s给service分配的ip
kubectl get service
通过请求service地址,访问nginx的index页面
curl 10.96.8.0:8000
可以看到,这个service负载均衡给所有nginx
或者在容器内部使用service域名,也可以访问
部署tomcat测试使用域名访问nginx
#创建一次部署,部署tomcat,podname叫my-tomcat
kubectl create deploy my-tomcat --image=tomcat
curl my-dep.default.svc:8000

我这里是使用的tomcat,在tomcat容器里面使用域名访问nginx,发现也是负债均衡的。注意:使用域名的方式,只能在容器内部,不可以直接在节点上访问,而使用IP的方式,可以直接在节点上使用;浏览器是无法通过ip的方式访问容器的nginx的,需要在kubesphere控制台页面配置应用路由,暴露这个端口后才可以访问
11、在k8s中进入容器内部,比如redis容器
kubectl exec -it redis -- redis-cli

12、K8s 集群中 503 错误排查指南。如果服务正常运行且没有任何错误日志,但是前端无法访问服务
1、问题分析
503 错误通常表示服务不可用,但您的 User 服务定时任务正常且无错误日志,这表明服务本身可能在运行,但无法响应外部请求。可能的原因包括:
- Ingress 配置错误
- Nginx Service 配置错误
- Pod 网络问题
- 健康检查失败
- 请求路由异常
2、排查步骤
1. 验证 Ingress 配置
# 检查Ingress资源定义
kubectl get ingress -n <namespace>
kubectl describe ingress <ingress-name>
# 检查规则是否正确指向服务,比如User Service
关键检查点:
- host 规则是否匹配请求域名
- path 规则是否正确(如/user对应 User 服务)
- backend 是否指向正确的 Service 和 Port
2. 检查 Nginx Service 配置
# 查看Service配置
kubectl get service -n <namespace>
kubectl describe service <nginx-service-name>
# 检查端口映射和选择器
关键检查点:
- port 和 targetPort 是否正确
- selector 是否匹配 Nginx Pod 的 labels
- type 是否为 LoadBalancer 或 NodePort(外部访问需要)
3. 验证 Nginx 内部配置
# 进入Nginx Pod查看配置
kubectl exec -it <nginx-pod-name> -n <namespace> -- bash
# 查看Nginx配置文件
cat /etc/nginx/nginx.conf
cat /etc/nginx/conf.d/*.conf
# 检查User服务的upstream配置
关键检查点:
- upstream 块是否正确指向 User Service 域名(如user-service..svc.cluster.local)
- proxy_pass 配置是否正确
4. 检查 User Service 健康状态
# 查看Service和Endpoint
kubectl get service <user-service-name> -n <namespace>
kubectl get endpoints <user-service-name> -n <namespace>
# 确认Endpoint是否有IP地址(表示Pod已就绪)
关键检查点:
- Endpoints 是否包含 User Pod 的 IP 和 Port
- 如果 Endpoint 为空,检查 Pod 的 Readiness/Liveness Probe 配置
5. 网络连通性测试
# 从Nginx Pod测试到User Service的连通性
kubectl exec -it <nginx-pod-name> -n <namespace> -- bash
curl http://user-service.<namespace>.svc.cluster.local:<port>/health
# 从Ingress Controller测试到Nginx的连通性
kubectl exec -it <ingress-pod-name> -n ingress-nginx -- curl http://<nginx-service-ip>:<port>
6. 检查 Ingress Controller 日志
# 获取Ingress Controller日志
kubectl logs -n ingress-nginx <ingress-controller-pod-name> | grep <user-service-name>
关键检查点:
- 是否有连接超时、拒绝等错误
- 是否正确路由到 Nginx Service
7. 检查 User Pod 网络策略
# 查看是否有NetworkPolicy限制流量
kubectl get networkpolicy -n <namespace>
关键检查点:
- 是否有策略阻止 Ingress→Nginx→User 的流量路径
3、常见问题解决方案
1. Ingress 规则错误
# 示例:正确的Ingress规则
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: user-ingress
spec:
rules:
- host: example.com
http:
paths:
- path: /user
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 80
2. Nginx 配置错误
# 示例:正确的Nginx upstream配置
upstream user_backend {
server user-service.<namespace>.svc.cluster.local:8080;
}
server {
listen 80;
location /user {
proxy_pass http://user_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
3. 健康检查问题
# 示例:添加Readiness Probe
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: user-container
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
4、验证修复效果
# 重新部署修改后的资源
kubectl apply -f ingress.yaml
kubectl apply -f nginx-config.yaml
# 检查Pod状态
kubectl get pods -n <namespace>
# 重试前端请求,检查是否恢复正常
13、快速生成一个yaml格式的文件
快速生成一个nginx的yaml
mkdir pratice/
cd pratice/
#命令解释
#kubectl create deployment nginx:创建一个nginx的deployment
#--image:镜像来源
#--replicas=3:表示副本数
#-oyaml:表示生成yaml格式
#--dry-run=client:表示执行的这个kubectl命令不落地,发给apiserver不持久化,也就不生成deployment
#> nginx-deployment.yaml:表示将生成的yaml输出到本地文件中
kubectl create deployment nginx --image=registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12-alpine --replicas=3 -oyaml --dry-run=client > nginx-deployment.yaml

十五、如果想安装旧版本的kubernetes、kubesphere,请点下方链接
旧版kubernetes、kubesphere详细安装步骤
https://blog.csdn.net/weixin_49186526/article/details/148349671?spm=1011.2415.3001.5331
更多推荐



所有评论(0)