综述
这篇笔记主要是为了记录下自己写 k8s 综合项目的过程。
由于自己之前已经写过简单的开发和运维项目,所以这里就结合一下,在搭建 k8s 集群后安装运维常用服务,比如 ansible 和 prometheus,用 NFS 实现数据存储同步,再部署一些制作成镜像的应用,进行压力测试,尝试发布,可以的话安装一些 CICD 相关软件,比如 gitlab、harbor、jenkins,主要是为了让自己更熟悉这些流程。
具体要达成的效果,就是实现容器化应用部署(通过 Kubernetes 部署和管理多个微服务应用)、监控和告警(使用 Prometheus 和 Grafana 进行集群和应用监控,及时发现和处理问题)、持久化存储(通过 NFS 提供持久化存储,支持应用的数据持久化)、负载均衡(通过 Ingress Controller 实现请求的负载均衡和路由)、弹性伸缩(通过 HPA 实现基于资源使用情况的自动扩缩容)、CI/CD流水线(使用 GitLab、Harbor 和 Jenkins 实现持续集成和持续部署,自动化构建和发布流程)、故障恢复(通过探针和监控实现故障检测和自动恢复)等。
这个项目不仅可以帮助团队更高效地开发和部署应用,还能提升运维的自动化程度。
项目过程
安装虚拟机
因为安装虚拟机的部分在前面的笔记里有一步步介绍个过,所以这里就不再展开介绍了。
最后开启虚拟机前记得选择对应的镜像文件。
在xshell登录后为了后续方便分辨机器,可以先自行修改主机名,这里用节点二为例。
这里在进行一切后续操作之前必须换一个国内源,原理和操作在之前的 docker 笔记都提过了,这里也就不再展开介绍。
这里安装 net-tools 是为了后面查看网络连接、路由表、接口统计等信息。。
对应的 netstat 命令可以帮助用户了解系统的网络状态,包括当前打开的TCP和UDP端口、网络连接的状态等。
修改为静态IP
这里进入根目录下的 network-scripts 是为了修改静态IP,避免之后IP变化影响k8s集群配置。
这一步就是为了方便修改,也可以免去这步,直接用 nano 编辑文件也可以。
这里是顺便先安装了扩展源,避免之后安装遇到阻碍。
这里编辑网关相关文件。
下面是具体修改内容。
只需修改红框内的内容,其他的不用管。网关地址的配置只需确保其唯一即可。
还可以加入上图的DNS信息,这是网络配置文件中的一行,用于指定 DNS(域名系统)服务器的地址。这里的 8.8.8.8 是 Google 提供的公共 DNS 服务器地址。
这里的 114.114.114.114 是由中国电信提供的一家公共 DNS 服务器,由于该 DNS 服务器位于中国,通常对于国内用户的访问速度较快,且相对稳定。
修改后重启一下。
查询后出现上面的结果表明修改静态IP成功。
配置到这里后,如果为了方便,其实另外几台 master 或者 node 可以直接克隆配置好的这台,我因为电脑也带不动太多,所以这几台都是一个个配置的。
配置主机清单
配置 hosts 文件,通过主机名互相访问。
关闭SELINUX
这是为了避免权限问题,因为Kubernetes 和容器化应用程序可能会与 SELinux 的默认策略发生冲突,从而影响 Pod 的运行。
# 临时关闭
setenforce 0
# 永久关闭
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
# 修改selinux配置文件之后,重启机器,selinux配置才能永久生效
reboot
# 检查
getenforce
# 显示Disabled说明selinux已经关闭
关闭firewalld和iptables
firewalld 是一种动态防火墙管理工具,使用 zones 和 services 来管理网络流量。
关闭 firewalld 是为了避免网络干扰,在 Kubernetes 集群中,Pod 之间的通信依赖于网络流量的开放,关闭 firewalld 可以避免防火墙规则阻止 Pod 之间的流量;关闭 firewalld 可以减少网络配置的复杂性,特别是在调试和测试环境中。
iptables 是 Linux 内核的一个组件,用于配置网络流量过滤规则。
关闭 iptables 是为了避免流量阻塞,在 Kubernetes 中,Pod 之间的流量可能会受到 iptables 规则的影响,闭 iptables 可以确保所有流量不受限制地通过; 关闭 iptables 可以简化网络管理,尤其是在调试和开发环境中。
systemctl stop firewalld
systemctl disable firewalld
iptables -F
这条命令可以清除当前防火墙的所有规则。
下面是关闭交换分区的命令。
# 临时关闭
swapoff -a
# 永久关闭
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
# 或者 vim /etc/fstab ,进去注释 swap 那行
这一步的作用如下。
1、保证性能。Kubernetes 依赖于节点的内存进行资源调度和管理。如果系统启用了交换分区,Kubernetes 可能会将某些 Pod 调度到内存不足的节点上,而这些节点可能会因为使用交换空间而导致性能下降。
2、避免不确定性。启用交换分区可能导致 Pod 的 OOM(Out Of Memory)杀手在处理内存不足时做出不可预测的行为。Kubernetes 在内存管理方面假设节点的内存是固定的,使用交换空间可能打破这种假设。
3、提升稳定性。在 Kubernetes 中,关闭交换可以确保当节点的内存达到阈值时,Pod 能够正确地被 Kubernetes 调度和管理,避免出现性能瓶颈或服务中断。
调整内核参数
具体修改和查看的命令如下。
这里解释一下这里调整各个参数和命令的作用。
# 内核参数设置
net.bridge.bridge-nf-call-iptables = 1
# 该参数配置 Linux 内核的网络桥接(bridge)功能,允许 iptables 规则应用于通过桥接接口的流量
# 启用此参数后,所有通过 Linux 桥接转发的流量将经过 iptables 进行过滤
# 重要性
# 在 Kubernetes 中,Pod 之间的通信通常通过 Linux 桥接网络进行
# 启用此参数可以确保网络策略(Network Policies)和防火墙规则能够正确应用到 Pod 之间的流量
net.bridge.bridge-nf-call-ip6tables = 1
# 和上面的参数类似,但这是针对 IPv6 流量
# 它允许 ip6tables 规则应用于通过桥接接口的 IPv6 流量
# 重要性
# 如果 Kubernetes 集群支持 IPv6,启用此参数是必要的,因为可以以确保 IPv6 流量能够被正确过滤和管理
net.ipv4.ip_forward = 1
# 启用 IP 转发功能,这允许 Linux 内核在接收到数据包时,将其转发到其他网络接口
# 重要性
# 在 Kubernetes 集群中,Pod 需要能够与其他 Pod、服务以及外部网络通信
# 启用 IP 转发是实现这种通信的必要条件
sysctl -p
# 该命令用于重新加载 sysctl 配置文件中的所有参数
# 通常在更改 `/etc/sysctl.conf` 或其他 sysctl 配置文件后使用
# 重要性
# 通过重新加载参数,可以确保所有设置立即生效,而无需重启系统
modprobe br_netfilter
# 该命令用于加载 `br_netfilter` 内核模块。此模块提供了对桥接网络流量进行过滤的能力
# 重要性
# 在使用 Kubernetes 的网络桥接功能时,加载此模块是必要的,以确保 iptables 规则能够正确应用于桥接流量
lsmod | grep br_netfilter
# 该命令用于检查 `br_netfilter` 模块是否已加载。如果模块已被加载,它将显示相关信息
# 重要性
# 确保 `br_netfilter` 模块已加载是确保 Kubernetes 网络功能正常运作的关键步骤
# 总的来说,这些设置和命令主要用于配置 Kubernetes 集群的网络功能,确保流量能正确地通过 iptables 进行过滤和管理。启用这些参数和模块有助于实现更安全和高效的网络通信,确保 Pod 之间以及与外部网络的连接正常
这一步的作用如下。
1、优化性能。一些内核参数可以优化网络性能、内存管理和进程调度等。调整这些参数可以提高集群的整体性能和响应速度。
2、提高可靠性。某些参数(如 vm.swappiness)影响系统如何使用内存和交换。通过调整这些参数,可以更好地控制系统在内存不足时的行为,从而提高应用程序的可靠性。
3、适应容器化环境。Kubernetes 运行在容器之上,某些内核参数可能需要根据容器的特性进行调整,以确保容器能够高效运行。
自动加载内核模块
cat <<EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
overlay,这个模块用于支持 Overlay 网络。它允许创建虚拟网络,以便在不同主机上的容器之间进行通信。
br_netfilter,这个模块用于确保网络流量通过 Linux 桥接网络时可以被正确过滤。Kubernetes 中的网络插件通常需要这个模块来正确处理网络策略和防火墙规则。
可以用这条命令查看 br_netfilter 和 overlay 模块是否加载成功。
更新和配置软件源
上面其实也提到过,这里就简单放个代码。
cd /etc/yum.repos.d
rm -rf *
curl -O http://mirrors.aliyun.com/repo/Centos-7.repo
这里是额外的操作,最好执行,会使后续操作更加方便。
yum clean all && yum makecache fast
# 清理 YUM 缓存并快速生成新的缓存,以确保获取最新的包信息
yum install -y yum-utils
# 安装 yum-utils,以便使用额外的 YUM 工具
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 添加 Docker CE 的阿里云镜像仓库,以便后续可以方便地安装 Docker CE
配置ipvs功能
# 安装ipset和ipvsadm,主要是对ipvs进行传递参数的或者管理的
yum install ipset ipvsadm -y
# 添加需要加载的模块写入脚本文件
#modprobo 作用是加载模块到内核里
cat <<EOF > /etc/sysconfig/modules/ipvs.modules
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
# 为脚本文件添加执行权限
chmod +x /etc/sysconfig/modules/ipvs.modules
# 执行脚本文件
/bin/bash /etc/sysconfig/modules/ipvs.modules
# 重启
reboot
# 查看对应的模块是否加载成功
lsmod | grep -e ip_vs -e nf_conntrack_ipv4
reboot 重启之后再看模块是否加载成功。
配置时间同步
systemctl restart chronyd && systemctl enable chronyd
安装docker环境
如果之前安装过 docker,这里就需要先移除原有的环境,我这里因为都是全新安装的虚拟机,所以不需要,就只放个代码。
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
移除后重新下载。
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 总结
# Docker CE: 通过安装 docker-ce,用户可以获得 Docker 的核心功能
# Docker CLI: docker-ce-cli 使得用户能够通过命令行与 Docker 守护进程交互
# Containerd: containerd.io 提供了容器的运行时支持
# Buildx 插件: docker-buildx-plugin 使得用户能够使用更高级的构建功能
# Docker Compose 插件: docker-compose-plugin 允许用户使用 Docker CLI 管理多容器应用
配置docker服务自启动
# 启动docker
systemctl start docker
# 设置docker开机启动
systemctl enable docker
# 验证
systemctl status docker
启动 docker 并确保之后都会自启动后查看一下 docker 状态,是否在运行。
配置docker的国内镜像源加速
vim /etc/docker/daemon.json
# 下面是 daemon.json 里面的内容
{
"registry-mirrors": ["https://hub.docker-alhk.dkdun.com/"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
# 重启服务生效
systemctl daemon-reload
systemctl restart docker
配置cri-docker
kubernets 1.24版本后默认使用containerd做底层容器,需要使用cri-dockerd做中间层来与docker通信
如果下载多次失败,可以去Gitee里的一个开源点下载对应版本的到本机,再用xftp上传到各个虚拟机。
cri-dockerd:dockerd as a compliant Container Runtime Interface for Kubernetes - GitCodehttps://gitcode.com/gh_mirrors/cr/cri-dockerd/tags?presetConfig=%7B%22tags%22:23,%22release%22:0%7D
我后面下载rpm成功了,所以上面的就没再继续。
# 下载
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.8/cri-dockerd-0.3.8-3.el7.x86_64.rpm
# 安装
rpm -ivh cri-dockerd-0.3.8-3.el7.x86_64.rpm
# 重载系统守护进程
systemctl daemon-reload
# 修改配置文件
vim /usr/lib/systemd/system/cri-docker.service
# 修改第10行 ExecStart
# 改为
# ExecStart=/usr/bin/cri-dockerd --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9 --container-runtime-endpoint fd://
配置k8s集群环境
这里安装的是 k8s 1.28 版本。
安装kubectl
# 下载
curl -LO "https://dl.k8s.io/release/v1.28.2/bin/linux/amd64/kubectl"
# 检验 可选
curl -LO "https://dl.k8s.io/v1.28.2/bin/linux/amd64/kubectl.sha256"
echo "$(cat kubectl.sha256) kubectl" | sha256sum --check
# 安装
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
# 测试
kubectl version --client
配置k8s组件源
cat <<EOF | tee /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
EOF
# 更新索引缓冲
yum makecache
安装
# 安装
yum install -y install kubeadm-1.28.2-0 kubelet-1.28.2-0 kubectl-1.28.2-0 --disableexcludes=kubernetes
# 如果报错未找到就试试不指定版本
yum install -y install kubeadm kubelet kubectl --disableexcludes=kubernetes
# 设置自启动
systemctl enable --now kubelet
# kubeadm - 用来安装master节点上的组件(apiserver、etcd、scheduler等),部署k8s集群的
# kubelet - 用来对容器运行时软件进行管理的(管理docker的)
# kubectl - 用来输入k8s的命令的
集群初始化
kubeadm init
这一步仅在 master 节点执行。
kubeadm init --kubernetes-version=v1.28.2 \
--pod-network-cidr=10.224.0.0/16 \
--apiserver-advertise-address=master的IP \
--image-repository=registry.aliyuncs.com/google_containers \
--cri-socket=unix:///var/run/cri-dockerd.sock
其中,apiserver-advertise-address 记得替换为 master 节点IP。
成功后会提示以下信息。
在系统提示命令 " kubectl join xxx " 后追加 " --cri-socket unix:///var/run/cri-dockerd.sock "。
完整命令应该类似于 " kubeadm join master的IP地址:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxx --cri-socket unix:///var/run/cri-dockerd.sock "。
将 node 节点加入集群
将上面的那段密钥复制粘贴到其他节点内部。
完成后应该能得到以下结果。
# 在master上执行
kubectl get nodes
分配 worker
# 在master上执行
kubectl label node k8s-node-1 node-role.kubernetes.io/worker=worker
kubectl label node k8s-node-2 node-role.kubernetes.io/worker=worker
安装Calico网络插件
# master执行
wget https://docs.projectcalico.org/manifests/calico.yaml
kubectl apply -f calico.yaml
# 验证
kubectl get nodes
安装完成后,可以检查下。
这里发现有几个都拉起失败,这是因为我用的国内网,很多时候无法正常拉取国外镜像仓库的文件。暂时的解决办法是在网上另外下载缺失的这两个镜像文件,将其导入本地。
导入完成后可以再次检查,这时没有完成可能是需要等会儿,也可能是没有在所有节点导入,记得在所有节点导入需要的镜像文件。
下面这里就可以看出已经安装和启动完毕。
安装Dashboard
以下命令均只在 master 节点上执行。
下载安装
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
修改 Service 部分,改为 NodePort 对外暴露端口。
kind: Service
apiVersion: v1
metadata:
...
spec:
type: NodePort # 改为NodePort
kubectl apply -f recommended.yaml
查看
kubectl get pods,svc -n kubernetes-dashboard
这里可以等一等。
创建账号
创建 dashboard-access-token.yaml 文件。
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: v1
kind: Secret
metadata:
name: admin-user
namespace: kubernetes-dashboard
annotations:
kubernetes.io/service-account.name: "admin-user"
type: kubernetes.io/service-account-token
下面这一步是为了获取后面在网站上登录的 token 密码。
# 获取token
kubectl get secret admin-user -n kubernetes-dashboard -o jsonpath={".data.token"} | base64 -d
访问dashboard
# 获取端口
kubectl get svc -n kubernetes-dashboard
这里看得出端口是30275。
然后在浏览器上访问网址为 - " 集群ip:端口(https://ip:端口号)"(注意https)。
之后再输入上一步获取到的 token 即可。
安装Kuborad
任意节点执行,推荐 master 节点。
sudo docker run -d \
--restart=unless-stopped \
--name=kuboard \
-p 80:80 \
-p 10081:10081 \
-e KUBOARD_ENDPOINT="http://ip:80" \
-e KUBOARD_AGENT_SERVER_TCP_PORT="10081" \
-v /root/kuboard-data:/data \
eipwork/kuboard:v3
在浏览器输入 http://IP:80 即可访问 Kuboard v3.x 的界面,登录时的用户名为 admin ,密码为 Kuboard123,下面是进入后的界面。
安装kubectl命令自动补全
yum install bash-completion -y
# 临时设置自动补全
source <(kubectl completion bash)
# 永久设置自动补全
echo "source <(kubectl completion bash)" >> ~/.bashrc && bash
部署metric-server
下载
在 master 节点上执行。
wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.6.2/components.yaml
修改
修改140行左右。
原:
containers:
- args:
...
image: k8s.gcr.io/metrics-server/metrics-server:v0.6.2
修改后:
containers:
- args:
...
- --kubelet-insecure-tls # 添加这一行
image: admin4j/metrics-server:v0.6.2 # 修改镜像仓库地址
应用
kubectl apply -f components.yaml
查看
kubectl top nodes # 显示集群中各个节点的资源使用情况
kubectl top pods # 显示集群中各个Pod的资源使用情况
提示错误或者其他,可以等等再试,我就是等了会儿才执行成功。
下面这个命令是在查看日志,看是否有错误提示。
上面这个命令是查看集群里每个节点的详细信息。
安装prometheus和grafana
安装prometheus和node_exporter
这一步是用来监控集群的日常性能情况。
二进制安装
更加具体的步骤在前面的 prometheus 笔记里,这里只记录大概。
下面这步可做可不做,这里建文件夹只是为了清晰分类。
然后解压。
这步重命名也是可做可不做,这里只是为了简化目录名。
这里是临时和永久修改PATH变量,添加 prometheus 的路径,最后查看效果。
然后可以添加一个添加 service 方式管理,以后可以直接 systemctl stop/start prometheus来停止和启动 prometheus ,方便操作。
修改后需要重启服务以生效,然后用 systemctl 启动 prometheus,并查看进程情况。
这里是查看进程运行情况。
node 节点这边也很简单,先如法炮制把 node_exporter 传过来。
再写一个安装 node_exporter 的全过程脚本。
然后运行脚本。
这样就可以了。
在另外一个节点上也如法炮制,可以把脚本通过 xftp 传到本机,再从本机通过 xftp 传到另外节点上运行,也可以用 ansible,因为这里只是做一个小项目测试,所以我暂时没用 ansible,直接用的 xftp。
下一步就是修改 prometheus.yml 里的内容,添加监控的虚拟机。
下面是具体的修改内容。
修改后重启一下 prometheus 的服务,就可以去浏览器上用 master 节点的IP加上9090端口查看详情。
Yaml文件安装
这种安装方法主要在Kubernetes或类似容器编排平台上进行,依赖Kubernetes集群和相关组件(如kubectl、etcd等)。
主要的优势在于以下几点:
1、配置通过YAML文件进行管理,易于版本控制和复制。
2、可以使用 Kubernetes 的滚动更新等功能来更新 Prometheus 配置或版本。
3、可以利用 Kubernetes 的自动扩展、健康检查等功能。
4、轻松实现 Prometheus 的水平扩展和高可用性配置(如使用 StatefulSet 和 Headless Service)。
5、可以利用 Kubernetes 的持久化存储解决方案(如 PersistentVolume)来持久化Prometheus 数据。
6、与 Kubernetes 生态系统紧密集成,可以轻松与其他 Kubernetes 组件和服务(如Grafana、Alertmanager 等)进行集成和交互。
7、可以利用 Kubernetes 的日志收集、监控和告警等功能来增强 Prometheus 的功能。
prometheus 可以在 master 或任意节点安装,也可以在 kubernets 集群外的虚拟机上安装,我这里是在 master 节点上安装的。
首先需要根据二进制文件制作相应的镜像,我这里因为自己制作的镜像在后续一直有问题解决不了,所以在网上下载了一个镜像导入本地,这个文件我也在CSDN上传了。
然后创建 prometheus-service.yaml 文件,这一步是用于暴露 Prometheus 监控服务。上面是具体实施效果图,下面是 yaml 文件中的具体内容。
apiVersion: v1
kind: Service
metadata:
name: prometheus
namespace: prometheus
labels:
app: prometheus
spec:
type: NodePort
ports:
- port: 9090
targetPort: 9090
protocol: TCP
selector:
app: prometheus
component: server
然后创建 prometheus-deploy.yaml 文件,这一步是用来定义 Prometheus 在 Kubernetes 环境中的部署配置。
具体 yaml 文件内容如下。
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus-server
namespace: prometheus
labels:
app: prometheus
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
component: server
template:
metadata:
labels:
app: prometheus
component: server
annotations:
prometheus.io/scrape: 'false'
spec:
serviceAccountName: prometheus
containers:
- name: prometheus
image: prom/prometheus:v2.51.1
imagePullPolicy: IfNotPresent
command:
- prometheus
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.path=/prometheus
- --storage.tsdb.retention=720h
- --web.enable-lifecycle
ports:
- containerPort: 9090
protocol: TCP
volumeMounts:
- mountPath: /etc/prometheus
name: prometheus-config
- mountPath: /prometheus/
name: prometheus-storage-volume
volumes:
- name: prometheus-config
configMap:
name: prometheus-config
- name: prometheus-storage-volume
hostPath:
path: /data
type: Directory
还需要创建一个 prometheus-config.yaml 文件,这是Prometheus监控系统的核心配置文件。它的主要作用是定义Prometheus的运行参数、监控目标(scrape targets)、告警规则等,内容如下。
kind: ConfigMap
apiVersion: v1
metadata:
labels:
app: prometheus
name: prometheus-config
namespace: prometheus
data:
prometheus.yml: |
global:
scrape_interval: 15s
scrape_timeout: 10s
evaluation_interval: 1m
scrape_configs:
- job_name: 'kubernetes-node'
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:9100'
target_label: __address__
action: replace
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- job_name: 'kubernetes-node-cadvisor'
kubernetes_sd_configs:
- role: node
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- target_label: __address__
replacement: kubernetes.default.svc:443
- source_labels: [__meta_kubernetes_node_name]
regex: (.+)
target_label: __metrics_path__
replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
- job_name: 'kubernetes-apiserver'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
- job_name: 'kubernetes-service-endpoints'
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
action: replace
target_label: __scheme__
regex: (https?)
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
action: replace
target_label: kubernetes_name
然后需要在其它需要被监控的节点安装 node_exporter。
首先制作 node_exporter 镜像文件,具体内容如下。
FROM alpine:latest
# 设置工作目录
WORKDIR /node_exporter
# 将node_exporter的二进制文件复制到镜像中
# 注意:这里假设node_exporter的二进制文件已经在本地的./node_exporter目录下
COPY ./node_exporter/node_exporter /node_exporter/node_exporter
# 暴露node_exporter的默认端口(9100)
EXPOSE 9100
# 设置容器启动时运行的命令
# 注意:node_exporter通常不需要额外的配置文件或参数
CMD ["/node_exporter/node_exporter"]
# 将日志输出到一个特定的目录
VOLUME ["/node_exporter/logs"]
制作完成后打上标签,上传到私人镜像仓库,我这里是上传到自己在阿里云的镜像仓库。
最后在 node-exporter.yaml 文件里设置好镜像文件的名字和拉取方式。
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: prometheus
labels:
name: node-exporter
spec:
selector:
matchLabels:
name: node-exporter
template:
metadata:
labels:
name: node-exporter
spec:
hostPID: true
hostIPC: true
hostNetwork: true
containers:
- name: node-exporter
image: registry.cn-hangzhou.aliyuncs.com/syr030111/node_exporter:1.4.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9100
securityContext:
privileged: true
volumeMounts:
- name: dev
mountPath: /host/dev
- name: proc
mountPath: /host/proc
- name: sys
mountPath: /host/sys
- name: rootfs
mountPath: /rootfs
tolerations:
- key: "node-role.kubernetes.io/master"
operator: "Exists"
effect: "NoSchedule"
volumes:
- name: proc
hostPath:
path: /proc
- name: dev
hostPath:
path: /dev
- name: sys
hostPath:
path: /sys
- name: rootfs
hostPath:
path: /
如果不行或者镜像拉取失败,大概率是需要制作拉取凭证,格式类似下面。
kubectl create secret docker-registry <secret-name> \
--docker-server=registry.<region>.aliyuncs.com \
--docker-username=<阿里云用户名> \
--docker-password=<阿里云密码> \
--docker-email=<邮箱> \
--namespace=<命名空间>
下面是成功的效果图。
安装grafana
首先用 xftp 传输本地下载好的 grafana 镜像文件,再导入。(这个镜像文件我也已经上传)
然后创建 grafana.yaml 文件,具体内容如下。
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
namespace: prometheus
spec:
replicas: 1
selector:
matchLabels:
app: grafana
template:
metadata:
labels:
app: grafana
spec:
containers:
- name: grafana
image: docker.io/grafana/grafana:10.4.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3000
protocol: TCP
volumeMounts:
- mountPath: /etc/ssl/certs
name: ca-certificates
readOnly: true
env:
- name: INFLUXDB_HOST
value: monitoring-influxdb
- name: GF_SERVER_HTTP_PORT
value: "3000"
- name: GF_AUTH_BASIC_ENABLED
value: "false"
- name: GF_AUTH_ANONYMOUS_ENABLED
value: "true"
- name: GF_AUTH_ANONYMOUS_ORG_ROLE
value: Admin
- name: GF_SERVER_ROOT_URL
value: /
volumes:
- name: ca-certificates
hostPath:
path: /etc/ssl/certs
---
apiVersion: v1
kind: Service
metadata:
labels:
name: grafana
name: grafana
namespace: prometheus
spec:
ports:
- port: 3000
targetPort: 3000
selector:
app: grafana
type: NodePort
上面查询到端口号32463后去浏览器登录进入。
安装NFS服务
搭建NFS服务器
准备服务器,这一步可以在 kubernets 集群之外的虚拟机上进行,也可以在集群内的任一节点进行。
yum install nfs-utils -y
创建共享目录,给文件修改权限。
make -p /data/nfs
chmod 777 /data/nfs
添加共享目录的配置。
/data/nfs *(rw,sync,no_subtree_check)
# rw表示读写权限
# sync表示同步写入
# no_subtree_check表示不检查父目录的变化(提高性能)
创建持久卷
剩下的步骤主要是构建三个 yaml 文件。
创建一个 yaml 文件,定义 NFS 持久卷。
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
spec:
capacity:
storage: 10Gi # 指定存储容量
accessModes:
- ReadWriteMany # 指定访问模式
nfs:
server: 192.168.31.192
path: /data/nfs
创建一个 yaml 文件,定义持久卷声明。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
spec:
accessModes:
- ReadWriteMany # 与 PV 的访问模式匹配
resources:
requests:
storage: 5Gi
在 Pod 的定义文件中,添加对 NFS 持久卷的引用,这里为 nginx 添加提供静态文件服务。
apiVersion: v1
kind: Pod
metadata:
name: test-nfs-volume
spec:
containers:
- name: test-nfs
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- name: nfs-volumes
mountPath: /usr/share/nginx/html
volumes:
- name: nfs-volumes
nfs:
path: /data/nfs
server: 192.168.31.192
显示下面的状态表示前面的操作成功。
客户端挂载共享目录
客户端和服务器需要下载的内容一致。
sudo yum install nfs-utils
然后在其他节点需要挂载共享目录,挂载成功后即可实时共享、修改存储数据。
vim /etc/fstab
服务器虚拟机ip:服务器上共享目录的路径 /mnt/NFS共享在本地系统上的挂载路径 nfs defaults 0 0
访问上面显示的IP,出现原始界面内容。
修改页面内容,这一操作在共享的任一虚拟机都可执行,效果一样。再次访问时发现修改成,这里的第二个修改权限操作不用管。
部署nginx
需要的几个 yaml 文件内容如下。
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-deployment-labels
name: nginx-deployment
spec:
replicas: 2 # 设置副本数量
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest #镜像拉取地址
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80 #监听端口
protocol: TCP
name: http
- containerPort: 443
protocol: TCP
name: https
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-service-label
name: nginx-service
spec:
selector:
app: nginx
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
nodePort: 30030 #nortPort开在主机的端口
- name: https
port: 443
protocol: TCP
targetPort: 443
nodePort: 30443
selector:
app: nginx
type: NodePort # 这里使用LoadBalancer类型,如果在本地运行,可以使用NodePort类型或ClusterIP类型
查看创建是否成功。
部署自己的应用(微服务)
这里用我自己制作的一个网站镜像文件举例,下面是其 Dockerfile 内容。
这是其相关 yaml 文件的具体内容。
apiVersion: apps/v1
kind: Deployment
metadata:
name: utopia-app-deployment
labels:
app: utopia-app
spec:
replicas: 2
selector:
matchLabels:
app: utopia-app
template:
metadata:
labels:
app: utopia-app
spec:
containers:
- name: utopia-app #pod名字
image: registry.cn-hangzhou.aliyuncs.com/syr030111/utopia:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080 # 容器内部端口
protocol: TCP
name: http
- containerPort: 999
protocol: TCP
name: https
---
apiVersion: v1
kind: Service
metadata:
name: utopia-app-service
spec:
type: NodePort
selector:
app: utopia-app #选择有该标签的pod容器
ports:
- name: http
protocol: TCP
port: 888 #service的端口
targetPort: 8080 #pod的端口,一般与pod内部容器的服务端口一致
其中 Deployment 负责创建和管理 Pod 的副本,确保指定数量的 Pod 始终在运行。如果 Pod崩溃或被删除,Deployment 会自动创建新的 Pod 来替换它们。
Service 允许我们访问 Pod 集合,并提供了负载均衡和访问控制的功能。这里的 Service 通过NodePort 类型在集群的每个节点上暴露了一个端口(通常是30000-32767之间的随机端口,但可以通过配置指定端口),从而允许从集群外部通过 IP:NodePort 的方式访问到 Pod 中的服务。
可以用下面几条命令查询是否创建成功。
如果出现类似下面的问题,即节点一直未准备好,可以用更下面的几个命令查询具体信息。
" kubectl describe nodes " 这个命令可以非常详细地查询各个节点的信息,也包括资源和内存使用情况。
下面这个可以简洁查询节点资源使用情况。
如果出现下面的超时错误可多尝试几次。
后续因为电脑空间不够,只能删除虚拟机,这个项目停在这里,之后有空间或者换电脑了继续。