从零开始:使用 Kubernetes 部署 Nginx 应用

这篇具有很好参考价值的文章主要介绍了从零开始:使用 Kubernetes 部署 Nginx 应用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

[root@icv-k8s-node-1 ~]# kubectl create deployment javaedge-nginx --image=nginx:1.24.0
deployment.apps/javaedge-nginx created
[root@icv-k8s-node-1 ~]# kubectl get all
NAME                                  READY   STATUS    RESTARTS   AGE
pod/javaedge-nginx-6996b98cc4-f28r2   1/1     Running   0          29s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   17h

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/javaedge-nginx   1/1     1            1           29s

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/javaedge-nginx-6996b98cc4   1         1         1       29s
[root@icv-k8s-node-1 ~]# kubectl get all -o wide
NAME                                  READY   STATUS    RESTARTS   AGE   IP             NODE             NOMINATED NODE   READINESS GATES
pod/javaedge-nginx-6996b98cc4-f28r2   1/1     Running   0          15m   10.244.26.65   icv-k8s-node-2   <none>           <none>

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   17h   <none>

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES         SELECTOR
deployment.apps/javaedge-nginx   1/1     1            1           15m   nginx        nginx:1.24.0   app=javaedge-nginx

NAME                                        DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES         SELECTOR
replicaset.apps/javaedge-nginx-6996b98cc4   1         1         1       15m   nginx        nginx:1.24.0   app=javaedge-nginx,pod-template-hash=6996b98cc4
[root@icv-k8s-node-1 ~]# 

可见,这个 nginx 并没有创建在 master 节点, 而是 slave 节点去了。

1 端口暴露

pod的8088端口作为容器的8080端口进行映射,pod要对外提供访问,需要实现service服务,有了
service才能被访问。可以认为service是管理一组pod的。 NodePort:把服务对外暴露公开

[root@icv-k8s-node-1 ~]# kubectl expose deployment javaedge-nginx  --port=90 --target-port=80 --type=NodePort
service/javaedge-nginx exposed

[root@icv-k8s-node-1 ~]# kubectl get all
NAME                                  READY   STATUS    RESTARTS   AGE
pod/javaedge-nginx-6996b98cc4-f28r2   1/1     Running   0          29m

NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/javaedge-nginx   NodePort    10.99.205.238   <none>        90:32708/TCP   3m48s
service/kubernetes       ClusterIP   10.96.0.1       <none>        443/TCP        18h

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/javaedge-nginx   1/1     1            1           29m

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/javaedge-nginx-6996b98cc4   1         1         1       29m
[root@icv-k8s-node-1 ~]# 
  • 90:32708/TCP 中的 90 是 Service 的端口
  • 32708 是 NodePort 的端口,表示该 Service 被映射到了 Node 上的 32708 端口

因此,对外暴露的端口是 32708,而不是 90。在 k8s 集群中,可通过 <NodeIP>:<NodePort> 访问该 Service。

kubectl 部署nginx,Docker &amp;&amp; Kubernetes,kubernetes,nginx,docker,原力计划

添加了一个新的 Node 组件,表示 Kubernetes 集群中的一个 Node。该 Node 上运行着 ServiceNodePort 端口(即 NodePort: 32708)。ServiceNodePort 端口将被映射到 Node 上的该端口。因此,外部客户端可以通过 <NodeIP>:<NodePort> 的方式访问该 Service,并且 <NodeIP> 是该 Node 的 IP 地址,<NodePort>NodePort: 32708

浏览器访问:

kubectl 部署nginx,Docker &amp;&amp; Kubernetes,kubernetes,nginx,docker,原力计划

把其中一个node关机。 查看node状态,刚才关机的node已经是 not ready 了。但再次查看pod还有 nginx pod,这就实现中间件的容灾问题,一旦出现宕机,则可以恢复重启。

删除 service:

kubectl delete service/javaedge-nginx

删除 deployment:

kubectl delete deployment/deployment_name

2 动态扩缩容(弹性伸缩)

扩容

[root@icv-k8s-node-1 ~]# kubectl get allNAME                                  READY   STATUS    RESTARTS   AGE
pod/javaedge-nginx-6996b98cc4-gncwc   1/1     Running   0          13m

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   21h

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/javaedge-nginx   1/1     1            1           3h37m

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/javaedge-nginx-6996b98cc4   1         1         1       3h37m
[root@icv-k8s-node-1 ~]# kubectl scale --replicas=2 deployment javaedge-nginx
deployment.apps/javaedge-nginx scaled
[root@icv-k8s-node-1 ~]# kubectl get all
NAME                                  READY   STATUS    RESTARTS   AGE
pod/javaedge-nginx-6996b98cc4-gncwc   1/1     Running   0          13m
pod/javaedge-nginx-6996b98cc4-n4qkk   1/1     Running   0          8s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   21h

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/javaedge-nginx   2/2     2            2           3h37m

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/javaedge-nginx-6996b98cc4   2         2         2       3h37m
[root@icv-k8s-node-1 ~]#

当突然高并发时,就能临时扩容。

现在流量平稳了,咱们

缩容

[root@icv-k8s-node-1 ~]# kubectl scale --replicas=1 deployment javaedge-nginx
deployment.apps/javaedge-nginx scaled
[root@icv-k8s-node-1 ~]# kubectl get all
NAME                                  READY   STATUS    RESTARTS   AGE
pod/javaedge-nginx-6996b98cc4-gncwc   1/1     Running   0          16m

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   21h

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/javaedge-nginx   1/1     1            1           3h40m

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/javaedge-nginx-6996b98cc4   1         1         1       3h40m
[root@icv-k8s-node-1 ~]#

可见 pod/javaedge-nginx-6996b98cc4-n4qkk被干掉了

删除容器

kubectl get all
[root@icv-k8s-node-1 ~]# kubectl get all
NAME                                  READY   STATUS    RESTARTS   AGE
pod/javaedge-nginx-6996b98cc4-gncwc   1/1     Running   0          21m

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   21h

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/javaedge-nginx   1/1     1            1           3h45m

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/javaedge-nginx-6996b98cc4   1         1         1       3h45m
## 删除部署信息,pod也会随之删除
[root@icv-k8s-node-1 ~]# kubectl delete deployment.apps/javaedge-nginx
deployment.apps "javaedge-nginx" deleted
[root@icv-k8s-node-1 ~]# kubectl get all
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   21h
[root@icv-k8s-node-1 ~]# 
## 删除service信息
kubectl delete service/javaedge-nginx

3 负载均衡

之前设置那个是节点类型,现在使用集群类型,可以实现负载均衡 port: 集群端口 target-port: 内部nginx
默认端口 ClusterIP: 集群方式,k8s会自动分配一个集群ip。

新建deployment

[root@icv-k8s-node-1 ~]# kubectl create deployment edge-nginx --image=nginx:1.24.0
deployment.apps/edge-nginx created
[root@icv-k8s-node-1 ~]# kubectl get all
NAME                                  READY   STATUS    RESTARTS   AGE
pod/edge-nginx-6d57745bc8-pgmdk       1/1     Running   0          37s
pod/javaedge-nginx-6996b98cc4-m84s5   1/1     Running   0          7m49s

NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/javaedge-nginx   NodePort    10.109.194.31   <none>        90:31104/TCP   6m50s
service/kubernetes       ClusterIP   10.96.0.1       <none>        443/TCP        21h

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/edge-nginx       1/1     1            1           37s
deployment.apps/javaedge-nginx   1/1     1            1           7m49s

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/edge-nginx-6d57745bc8       1         1         1       37s
replicaset.apps/javaedge-nginx-6996b98cc4   1         1         1       7m49s
[root@icv-k8s-node-1 ~]# 

端口暴露

[root@icv-k8s-node-1 ~]# kubectl expose deployment edge-nginx  --port=88 --target-port=80 --type=ClusterIP
service/edge-nginx exposed
[root@icv-k8s-node-1 ~]# kubectl get all
NAME                                  READY   STATUS    RESTARTS   AGE
pod/edge-nginx-6d57745bc8-pgmdk       1/1     Running   0          77s
pod/javaedge-nginx-6996b98cc4-m84s5   1/1     Running   0          8m29s

NAME                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/edge-nginx       ClusterIP   10.106.187.202   <none>        88/TCP         13s
service/javaedge-nginx   NodePort    10.109.194.31    <none>        90:31104/TCP   7m30s
service/kubernetes       ClusterIP   10.96.0.1        <none>        443/TCP        21h

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/edge-nginx       1/1     1            1           77s
deployment.apps/javaedge-nginx   1/1     1            1           8m29s

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/edge-nginx-6d57745bc8       1         1         1       77s
replicaset.apps/javaedge-nginx-6996b98cc4   1         1         1       8m29s
[root@icv-k8s-node-1 ~]# 

所以啊,不能随便命名。

扩容

[root@icv-k8s-node-1 ~]# kubectl scale --replicas=3 deployment edge-nginx
deployment.apps/edge-nginx scaled
[root@icv-k8s-node-1 ~]# kubectl get all
NAME                                  READY   STATUS    RESTARTS   AGE
pod/edge-nginx-6d57745bc8-dm998       1/1     Running   0          9s
pod/edge-nginx-6d57745bc8-pgmdk       1/1     Running   0          3m57s
pod/edge-nginx-6d57745bc8-zsw9v       1/1     Running   0          9s
pod/javaedge-nginx-6996b98cc4-m84s5   1/1     Running   0          11m

NAME                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/edge-nginx       ClusterIP   10.106.187.202   <none>        88/TCP         2m53s
service/javaedge-nginx   NodePort    10.109.194.31    <none>        90:31104/TCP   10m
service/kubernetes       ClusterIP   10.96.0.1        <none>        443/TCP        21h

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/edge-nginx       3/3     3            3           3m57s
deployment.apps/javaedge-nginx   1/1     1            1           11m

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/edge-nginx-6d57745bc8       3         3         3       3m57s
replicaset.apps/javaedge-nginx-6996b98cc4   1         1         1       11m
[root@icv-k8s-node-1 ~]# curl http://10.106.187.202:88/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@icv-k8s-node-1 ~]# 

nginx返回都一样的,如何测试实现了负载均衡呢?我们来通过 k8s(而不是 docker 的docker exec -it了)进入容器内部,而 pod 才是 k8s 最小单位,所以进入 pod 的 name 即可:

[root@icv-k8s-node-1 ~]# kubectl exec -it edge-nginx-6d57745bc8-dm998 -- /bin/bash
root@edge-nginx-6d57745bc8-pgmdk:/# cd /usr/share/nginx/html
root@edge-nginx-6d57745bc8-dm998:/usr/share/nginx/html# apt-get update
root@edge-nginx-6d57745bc8-dm998:/usr/share/nginx/html# apt-get install
root@edge-nginx-6d57745bc8-zsw9v:/usr/share/nginx/html# vim index.html

kubectl 部署nginx,Docker &amp;&amp; Kubernetes,kubernetes,nginx,docker,原力计划

ctrl+d退出当前 pod,再对其他两个副本同样操作即可。

重新访问集群 ip:

curl http://10.106.187.202:88/

你就会发现打印了不同的 JavaEdge 00x。

注:如果动态扩容,新的nginx节点会自动加入pod,进入负载均衡的效果

4 yml描述文件

前面我们部署操作nginx容器的时候,都是通过敲命令的方式进行的,其实很繁琐,一不小心就会失败。

我们可以通过yaml配置文件来实现容器的部署,不需要再写命令行了。yaml其实就是对象描述文件,我
们把要实现的容器作为一个对象去声明,指定他的相关属性即可。

比如可将:

  • 部署deployment作为yaml
  • 构建pod作为yaml
  • 实现负载均衡作为yaml
  • 构建service作为yaml
  • ……都可以

通过运行: kubectl apply -f xxx.yaml 可以实现文件中的内容。

apiVersion: apps/v1 ## 同k8s集群版本⼀致,通过kubectl api-versions查看
kind: Deployment ## 本配置⽂件的类型
metadata: ## 元数据,配置的⼀些基本属性和信息
  name: nginx-deployment ## 当前 Deployment 的命名
  labels: ## 标签,定义⼀个或多个资源,类似于 docker t
    app: nginx ## 设置key为app,value为nginx的标签
spec: ## 当前 Deployment 的具体描述,在k8s中的配置
  replicas: 2 ## 指定将要部署的应⽤副本数
  selector: ## 标签选择器,同上labels
    matchLabels: ## 匹配并选择包含标签app:nginx的相关资源
      app: nginx
  template: ## 使⽤Pod模板
    metadata: ## Pod元数据
      labels: ## Pod标签选择,选择包含[app:nginx]标签的Po
        app: nginx
    spec: ## 定义Pod中的容器详细描述
      containers: ## 同docker中的容器

      - name: my-nginx ## 容器名称
        image: nginx:1.24.0 ## 容器所使用的镜像名称及版本号
[root@icv-k8s-node-1 home]# vim ngx-k8s_deployment.yaml
[root@icv-k8s-node-1 home]# kubectl apply -f ngx-k8s_deployment.yaml
deployment.apps/nginx-deployment created
[root@icv-k8s-node-1 home]# 

kubectl 部署nginx,Docker &amp;&amp; Kubernetes,kubernetes,nginx,docker,原力计划

现在想

4.1 缩容到一个咋办?

修改 yaml

副本数改成 1 即可:

kubectl 部署nginx,Docker &amp;&amp; Kubernetes,kubernetes,nginx,docker,原力计划

apply
[root@icv-k8s-node-1 home]# kubectl apply -f ngx-k8s_deployment.yaml
deployment.apps/nginx-deployment configured
[root@icv-k8s-node-1 home]# 

现在 pod 数和副本数都变成 1 了:

kubectl 部署nginx,Docker &amp;&amp; Kubernetes,kubernetes,nginx,docker,原力计划

[root@icv-k8s-node-1 home]# kubectl expose deployment nginx-deployment  --port=88 --target-port=80 --type=NodePort --dry-run -o yaml
W0630 15:27:30.699552    3888 helpers.go:692] --dry-run is deprecated and can be replaced with --dry-run=client.
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx-deployment
spec:
  ports:
  - port: 88
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: NodePort
status:
  loadBalancer: {}
[root@icv-k8s-node-1 home]# 

对此,新建一个 yaml:

apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx-deployment
spec:
  ports:
  - port: 89
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: NodePort
status:
  loadBalancer: {}
[root@icv-k8s-node-1 home]#  kubectl apply -f k8s_ngx_expose.yaml
service/nginx-deployment created
[root@icv-k8s-node-1 home]# 

kubectl 部署nginx,Docker &amp;&amp; Kubernetes,kubernetes,nginx,docker,原力计划

根据该端口访问也没问题:

kubectl 部署nginx,Docker &amp;&amp; Kubernetes,kubernetes,nginx,docker,原力计划

根据已有 pod 生成对应 yaml

[root@icv-k8s-node-1 home]# kubectl get pod edge-nginx-6d57745bc8-dm998 -o yaml > k8s_ngx_pod.yaml
[root@icv-k8s-node-1 home]# vim k8s_ngx_pod.yaml
[root@icv-k8s-node-1 home]# 

如果想先创建 deployment,再创建 service,也可写在一个 yaml 文件里,只要两部分中间用“—”分割即可:

kubectl 部署nginx,Docker &amp;&amp; Kubernetes,kubernetes,nginx,docker,原力计划文章来源地址https://www.toymoban.com/news/detail-602983.html

到了这里,关于从零开始:使用 Kubernetes 部署 Nginx 应用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【云原生 | 从零开始学Kubernetes】二十三、Kubernetes控制器Statefulset

    该篇文章已经被专栏《从零开始学k8s》收录 上一篇文章:kubernetes持久化存储下 点击跳转 StatefulSet 是为了管理有状态服务的问题而设计的 对于StatefulSet中的Pod,每个Pod挂载自己独立的存储,如果一个Pod出现故障,从其他节点启动一个同样名字的Pod,要挂载上原来Pod的存储继续

    2024年02月03日
    浏览(32)
  • 从零开始学习K8s系列——Kubernetes指南

    作者:禅与计算机程序设计艺术 Kubernetes(简称k8s)是一个开源的,用于自动部署、扩展和管理容器化的应用的平台。它主要提供四大功能,包括: 服务发现和负载均衡 :Kubernetes集群中的服务能够自动地寻找其他运行着的服务并进行负载均衡。 存储编排 :Kubernetes允许用户

    2024年02月06日
    浏览(49)
  • 《Kubernetes部署篇:Ubuntu20.04基于二进制安装安装kubeadm、kubelet和kubectl》

    由于客户网络处于专网环境下, 使用kubeadm工具安装K8S集群 ,由于无法连通互联网,所有无法使用apt工具安装kubeadm、kubelet、kubectl,当然你也可以使用apt-get工具在一台能够连通互联网环境的服务器上下载kubeadm、kubelet、kubectl软件包,然后拷贝到专网主机上,通过dpkg工具安装

    2024年02月10日
    浏览(47)
  • Kubernetes高可用集群二进制部署(四)部署kubectl和kube-controller-manager、kube-scheduler

    Kubernetes概述 使用kubeadm快速部署一个k8s集群 Kubernetes高可用集群二进制部署(一)主机准备和负载均衡器安装 Kubernetes高可用集群二进制部署(二)ETCD集群部署 Kubernetes高可用集群二进制部署(三)部署api-server Kubernetes高可用集群二进制部署(四)部署kubectl和kube-controller-man

    2024年02月12日
    浏览(40)
  • Kubernetes 命令行工具 kubectl 安装和使用教程

    管理 Kubernetes 集群资源的唯一入口是通过调用 apiserver 的接口,kubectl 是官方提供的 CLI 命令行工具,kubectl 将用户在命令行输入的命令组织并转化为 apiserver 能识别的信息,进而实现对 Kubernetes 各种资源的管理功能。使用 kubectl 可以实现部署应用程序、检查和管理集群资源、查

    2024年02月06日
    浏览(42)
  • Kubernetes学习笔记-在多个集群中使用kubectl 20230623

    一、在Minikue和Google Kubernetes引擎之间切换 切换到Minikube $minikube start Starting local kubernetes cluster... ... Setting up kubeconfig... kubectl is now configured to use the cluster 从Minikube切换到GKE后,可以通过停止Minikube并重新切换回来。这时kubectl会被再次重新设置以适用于Minikube集群 切换到GKE $gcl

    2024年02月10日
    浏览(33)
  • 使用kubectl连接远程Kubernetes(k8s)集群

    你需要准备一个Kubernetes集群,你要记下你安装Kubernetes的版本。如图我已经准备好了一个版本号为 v1.21.14 的集群: 注意下载的版本号最好与你安装的Kubernetes版本对应上,各个版本的下载地址(⚠️注意修改url中的版本号): Windows: x86_64: arm64: MacOS: Intel: Apple Silicon: Linux: x86

    2024年02月04日
    浏览(58)
  • 【云原生 | 从零开始学Kubernetes】二十、Service代理kube-proxy组件详解

    该篇文章已经被专栏《从零开始学k8s》收录 上一篇文章:Kubernetes核心技术Service实战 点击跳转 Kubernetes service 只是把应用对外提供服务的方式做了抽象,真正的应用跑在 Pod 中的 container 里,我们的请求转到 kubernetes nodes 对应的 nodePort 上,那么 nodePort 上的请求是如何进一步转

    2024年02月03日
    浏览(39)
  • 【大模型研究】(1):从零开始部署书生·浦语2-20B大模型,使用fastchat和webui部署测试,autodl申请2张显卡,占用显存40G可以运行

    https://www.bilibili.com/video/BV1pT4y1h7Af/ 【大模型研究】(1):从零开始部署书生·浦语2-20B大模型,使用fastchat和webui部署测试,autodl申请2张显卡,占用显存40G可以运行 https://modelscope.cn/models/Shanghai_AI_Laboratory/internlm2-chat-20b/summary InternLM2 开源了一个 200 亿参数的基础模型和一个针对

    2024年01月22日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包