K8s(kubernetes)集群搭建及dashboard安装、基础应用部署

news2024/12/23 14:27:25

基础介绍

概念

本质是一组服务器集群,在集群每个节点上运行特定的程序,来对节点中的容器进行管理。实现资源管理的自动化。

功能

  • 自我修复
  • 弹性伸缩
  • 服务发现
  • 负载均衡
  • 版本回退
  • 存储编排

组件

  • 控制节点(master)-控制平面

APIserver:资源操作的唯一入口
scheduler :集群资源调度,将Pod调度到node节点上
controlManager:维护集群状态,程序部署状态
Etcd:存储各种资源对象信息(数据库-可替换)

  • 工作节点(node)-数据平面,提供数据环境

Kubelet:负责维护生命周期,创建、更新、销毁docker容器
Docker:容器操作
KuberProxy:集群内部服务发现和负载均衡

概念

  • Master:控制节点

  • Node:工作节点

  • Pod: 最小工作单元,容器运行在pod上

  • Controller:控制器,实现对pod的管理

  • Service:pod的统一入口

  • Label:标签,对pod分类

  • Namespace:命名空间,隔离pod环境

工作流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HMDSFZa4-1689145689993)(C:\Users\ricar\AppData\Roaming\Typora\typora-user-images\image-20230618235232615.png)]

集群搭建

类型:

  • 一主多从

  • 多主多从

基于三台机器搭建集群

环境配置

IP

192.168.1.220 ricardo-1    #主节点
192.168.1.221 ricardo-2    #从节点
192.168.1.222 ricardo-3    #从节点

关闭防火墙

#临时关闭
systemctl stop firewalld
#永久关闭
systemctl disable firewalld

关闭selinux

#永久关闭
sed -i '/selinux/s/enforcing/disabled/' /etc/selinux/config
#临时关闭
setenforce 0

关闭swap分区

# 临时关闭
swapoff -a   
# 注释到swap那一行  永久关闭
vim /etc/fstab 

设置主机名称

hostnamectl set-hostname ricardo-1
hostnamectl set-hostname ricardo-2
hostnamectl set-hostname ricardo-3

添加主机名与IP对应关系(三台主机都执行)

cat >> /etc/hosts << EOF
192.168.1.220 ricardo-1
192.168.1.221 ricardo-2
192.168.1.222 ricardo-3
EOF

将桥接的IPv4流量传递到iptables的链(三台主机都执行):

cat > /etc/sysctl.d/k8s.conf << EOF
net.ipv4.ip_forward = 1
net.ipv4.tcp_tw_recycle = 0
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system

时间同步

yum install ntpdate -y
ntpdate time.windows.com

Docker安装

安装需要的软件包, yum-util 提供yum-config-manager功能

yum install -y yum-utils device-mapper-persistent-data lvm2

设置 yum 源(阿里云)

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

选择docker版本并安装

yum list docker-ce --showduplicates | sort -r

安装

sudo yum install -y docker-ce-19.03.0 docker-ce-cli-19.03.0

配置镜像加速

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
	"exec-opts": ["native.cgroupdriver=systemd"],
	"registry-mirrors": ["https://5w5kf152.mirror.aliyuncs.com"]
}
EOF

启动 Docker 并设置开机自启

systemctl restart docker && systemctl enable docker

K8s安装

添加阿里云 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

kubeadm、kubelet、kubectl 的安装(都安装)

版本对应关系

k8s与docker版本对应关系

#下载软件
yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0


#开机自启动
systemctl enable kubelet

在 Master 节点中部署集群-(只在master节点执行)

kubeadm init --kubernetes-version=1.18.0  \
--apiserver-advertise-address=192.168.1.220   \
--image-repository registry.aliyuncs.com/google_containers  \
--service-cidr=10.10.0.0/16 --pod-network-cidr=10.122.0.0/16

示例
成功示例

开启 kubectl 工具的使用(该命令在master节点中执行)

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

将 node 节点加入 master 中的集群(该命令在工作节点node中执行)。

kubeadm join 192.168.1.220:6443 --token 88gcei.gmh12c7jmh6ksgj6 \
 --discovery-token-ca-cert-hash sha256:8a3f8919183a5ff0fe8626615195a044a74b0ea3a004e41c013095d28eea83dc 
#重新创建
kubeadm token create --print-join-command

安装网络插件(CNI) 下面两个中选一个,

calico

# 下载calico插件的yaml
wget https://docs.projectcalico.org/v3.14/manifests/calico.yaml --no-check-certificate


#修改定义pod网络CALICO_IPV4POOL_CIDR的值
vim calico.yaml
# 修改定义pod网络CALICO_IPV4POOL_CIDR的值和kubeadm init pod-network-cidr的值一致
## 取消注释
- name: CALICO_IPV4POOL_CIDR
  value: "10.122.0.0/16"


kubectl apply -f calico.yaml

#查看运行状态
kubectl get pods -n kube-system


[root@ricardo-1 k8s]# kubectl get nodes
NAME        STATUS   ROLES    AGE   VERSION
ricardo-1   Ready    master   43m   v1.18.0
ricardo-2   Ready    <none>   41m   v1.18.0
ricardo-3   Ready    <none>   41m   v1.18.0

示例

pod

fannel(如果用了上面的calico就不要用这个了)

# 下载flannel插件的yml
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

# 修改kube-flannel.yml中的镜像仓库地址为国内源
sed -i 's/quay.io/quay-mirror.qiniu.com/g' kube-flannel.yml

# 安装网络插件
kubectl apply -f kube-flannel.yml

控制台-dashboard 安装

安装

#版本地址
https://github.com/kubernetes/dashboard/releases?page=1

#下载配置文件
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.4/aio/deploy/recommended.yaml

#修改 39行
spec:
 type: NodePort
 ports:
   - port: 443
     targetPort: 8443
     nodePort: 31001
 selector:
   k8s-app: kubernetes-dashboard

#启动
kubectl apply -f recommended.yaml

#查看
kubectl get pods -n kubernetes-dashboard

#打开网页
https://192.168.1.220:31001/
鼠标点击空白处,输入:thisisunsafe 

#服务器生成token(master节点)

#1、创建账号
kubectl create serviceaccount dashboard-admin -n kubernetes-dashboard


#2、创建集群角色权限绑定
kubectl create clusterrolebinding kube-dashboard-admin --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:dashboard-admin

#3、获取账号token
kubectl get secret -n kubernetes-dashboard | grep dashboard-admin

kubectl describe secrets dashboard-admin-token-zcvnc -n kubernetes-dashboard

#token  粘到 web端
eyJhbGciOiJSUzI1NiIsImtpZCI6InE5NHpxbWhwc0FmVjhhSUZ4bElhZ19JbXVfSXpPNkFhVHFyUE9vc1A5MkUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4temN2bmMiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMTc5YjdmYzItOWU2Ny00MTcwLThkYmYtZGJlODU0MzNhM2MxIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmVybmV0ZXMtZGFzaGJvYXJkOmRhc2hib2FyZC1hZG1pbiJ9.f_klKo1n-5cg0UEFodRojtd5hTs3BTL6tFNi0G6aZWalyJuQioodkM3pW1I2d7HaIaKP61XJPRyq9YZEQp9SHsa_guCXMF83JmF5yG8G0hAQbDWyO7DnaFnoGK1RcaH5PioyVOrCOZEYwzwEPtObeXeqnVzNFI4kR1cfIpRefpuhm8dKP06PNpiQRMhLPXWThw1LmCL0OmnPlKyVJJNi2toPS7jxG3LFMhJZR_DA3jOf9kFUXL_v29V2cRzRIU1_cN0t3wsmrPahV3D7LlHAnLVRaV6L-C6X5_l88WwDebDTm4Ag20MLLRE5zeLq6lFh38FWy86IOivinSavysWuwA

#修改token持续时间(默认 15分钟 600s)
修改命名空间  kubernetes-dashboard   deployment  kubernetes-dashboard

contaiiners下 args参数

新增 --token-ttl=43200


#日志
kubectl logs -f -n kubernetes-dashboard kubernetes-dashboard-7b544877d5-r4jjw

token
在这里插入图片描述
示意图

常用命令

# 获得节点
kubectl get nodes

#查看pod
kubectl get pods -A
kubectl get pods -n kube-system
kubectl get pod -n kube-system -o wide

#pod状态
kubectl describe pod coredns-57d4cbf879-xgk2f -n kube-system
kubectl logs -f coredns-57d4cbf879-xgk2f -n kube-system

#查看状态
systemctl status kubelet

systemctl status kubelet.service --now

#日志  -  节点日志
journalctl -f -u kubelet
journalctl -u kubelet

#开机自启动
systemctl enable  kubelet
#重启
systemctl restart kubelet
#查看状态
systemctl status  kubelet

#查看命名空间
kubectl get ns

#创建空间
kubectl create namespace dev

#重置
kubeadm reset
#reset后删除
rm -rf $HOME/.kube


# 查看k8s的pod网段和svc网段  kubeadm的配置信息存在config-map中
kubectl -n kube-system describe cm kubeadm-config |grep -i pod
# 查看pod网段和svc网段
kubectl -n kube-system describe cm kubeadm-config |grep -i net


部署第一个应用-Nginx

基础介绍

概念

  • Namespace 表示命名空间:应用需在命名空间下
  • Deployment :即发布pod,因为pod是最小单位
  • Service: 暴露服务到外部的方式,包括LoadBlancer Service、NodePort Service、Ingress,即配置一个对外访问的入口

基础流程

因此,部署应用的步骤基本是 先创建命名空间, 再创建pod,再创建service

1、创建命名空间

文件:nginx-namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
 name: dev
 labels:
   name: dev

名词:

kind:Namespace 表示yaml文件创建的是命名空间

metadata表示命名空间的元信息

metadata.name 是命名空间的名称 取值dev

metadata.labels 是命名空间的标签 name=dev

应用

kubectl create -f namespace-dev.yaml

2、创建Deployment

文件:deployment-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: nginx
 name: nginx-deployment1
 namespace: dev
spec:
 replicas: 3
 selector:
   matchLabels:
     app: nginx
 template:
   metadata:
     labels:
       app: nginx
   spec:
     containers:
     - image: nginx:1.14.0
       ports:
       - containerPort: 80
       name: nginx

以下参数自定义时可选

   spec:
     containers:
     - image: nginx:1.14.0
       ports:
       - containerPort: 80
       name: nginx
       volumeMounts: #k8s的master服务器对应的路径,必须存在
       - name: conf
         mountPath: /etc/nginx/nginx.conf
       - name: log
         mountPath: /var/log/nginx
       - name: html
         mountPath: /etc/nginx/html
     tolerations:
     - key: "key"
       operator: "Equal"
       value: "nginx"
       effect: "NoSchedule"
     volumes: #k8s的node对应的路径
     - name: conf #和volumeMounts中的内容要对应
       hostPath:
         path: /Users/w/kube/nginx/conf/nginx.conf
    - name: log #和volumeMounts中的内容要对应
       hostPath:
         path: /Users/w/kube/nginx/logs
         type: Directory
     - name: html #和volumeMounts中的内容要对应
       hostPath:
         path: /Users/w/kube/nginx/html
         type: Directory

名词:

kind: Deployment表示yaml文件创建的是一个Deployment发布
metadata表示这个deployment的元信息
metadata.name 是deployment的名称 nginx-deployment1
metadata.labels 是deployment的标签 即:app=nginx
metadata.namespace 是deployment的命名空间,此处选择的是第一步创建的命名空间nginx

spec: 表示deployment的详细参数配置说明
spec.replicas 是启动几个pod节点
spec.template.spec 是deployment选择模块的详细说明
spec.template.spec.containers 表示选择的容器是什么,此处是nginx的docker镜像 nginx:1.14.0,容器的端口设置 containerPort: 80, volumeMounts表示绑定的文件和目录

spec.template.spec.volumes 表示选择的容器挂载的宿主机的文件和目录 conf, log和html

应用:

kubectl create -f deployment-nginx.yaml #初次创建
kubectl apply -f deployment-nginx.yaml #后期更新

#查看
kubectl get pods -n dev
kubectl describe pod nginx-deployment1-6cb86fb6b7-kkpbw -n dev
kubectl delete pod nginx-deployment1-6cb86fb6b7-txkkj -n dev
kubectl describe deployment nginx -n dev

3、创建service

文件:service-nginx.yaml

apiVersion: v1
kind: Service
metadata:
 labels:
  app: nginx
 name: nginx-deployment1
 namespace: dev
spec:
 ports:
 - port: 9000
   protocol: TCP
   targetPort: 80
   nodePort: 31090
 selector:
   app: nginx
 type: NodePort

名词:

kind: Service表示yaml文件创建的是一个Service

metadata表示这个Service的元信息

metadata.name 是Service的名称 nginx-deployment1

metadata.labels 是Service的标签 即:app=nginx

metadata.namespace 是Service的命名空间,此处选择的是第一步创建的命名空间nginx

sepc是Service的详细配置说明

sepc.type 取值NodePort 表示这个Service的类型是一个节点端口转发类型

sepc.selector 表示这个Service是将带标签的哪些pods做为一个集合对外通过服务

sepc.ports.port 是Service绑定的端口

sepc.ports.name: nginx-service80 表示Service服务的名称
sepc.ports.protocol: TCP 表示Service转发请求到容器的协议是TCP,我们部署的http的nginx服务,因此选择协议为TCP
sepc.ports.targetPort: 80 表示Service转发外部请求到容器的目标端口80,即deployment的pod容器对外开放的容器端口80
sepc.ports.nodePort: 31090 表示Service对外开放的节点端口

应用

kubectl apply -f service-nginx.yaml


#查看
kubectl get services -n dev
kube kubectl describe service nginx-deployment1 -n nginx
kubectl delete services nginx-deployment1 -n nginx

4、测试

地址

192.168.1.220:31090

效果:
在这里插入图片描述

报错解决

错误描述 dial tcp 10.96.0.1:443: connect: no route to host

  • systemctl stop docker
  • systemctl stop kubelet
  • iptables --flush
  • iptables -tnat --flush
  • systemctl start kubelet
  • systemctl start docker

错误 Unable to update cni config: No networks found in /etc/cni/net.d

mkdir -p /etc/cni/net.d

cat > /etc/cni/net.d/10-flannel.conflist << EOF
{
  "name": "cbr0",
  "plugins": [
    {
      "type": "flannel",
      "delegate": {
        "hairpinMode": true,
        "isDefaultGateway": true
      }
    },
    {
      "type": "portmap",
      "capabilities": {
        "portMappings": true
      }
    }
  ]
}
EOF

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/745472.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VMware ESXi 7.0 Update 3n - 领先的裸机 Hypervisor

VMware ESXi 7.0 Update 3n - 领先的裸机 Hypervisor VMware ESXi 7.0 Update 3n Standard & All Custom Image for ESXi 7.0 U3m Install CD 更新日期&#xff1a;Fri Jul 07 2023 10:50:00 GMT0800&#xff0c;阅读量: 4518 请访问原文链接&#xff1a;https://sysin.…

全网最细,Web自动化测试-数据驱动实战,直接通关...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 在Web自动化测试中…

智能照明控制系统在民用照明节能中的应用

摘 要 &#xff1a;通过智能照明控制系统在某宾馆电气工程中的应用实例&#xff0c;从照明控制的系统结构、设计及系统软件等方面&#xff0c;介绍了智能照明控制系统的功能及实现方式。探讨了智能照明控制系统在民用建筑中的适用范围和发展前景&#xff0c;并由此进一步推断智…

运维小知识(二)——Linux大容量磁盘分区及挂载

centos系统安装&#xff1a;链接 目录 1.&#x1f353;&#x1f353;命令格式化磁盘 2.&#x1f353;&#x1f353;大容量硬盘分区 3.&#x1f353;&#x1f353;自动挂载 整理不易&#xff0c;欢迎一键三连&#xff01;&#xff01;&#xff01; 新系统装完之后&#xff0…

基于appium的常用元素定位方法

目录 一、元素定位工具 1.uiautomatorviewer.bat 2.appium检查器 二、常用元素定位方法 1.id定位 2.class_name定位 3.accessibility_id定位 4.android_uiautomator定位 5.xpath定位 三、组合定位 四、父子定位 五、兄弟定位 一、元素定位工具 app应用的元素使用的是控…

前端实战(四):Nginx代理

Nginx的用处 Nginx的作用主要体现在作为 Web 服务器、负载均衡服务器、邮件代理服务器等方面&#xff0c;其特点是占有内存少&#xff0c;并发能力强&#xff0c;给使用者带来了很多的便利。Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&…

【UE4 C++】06-绑定运动输入(实现前后移动、鼠标转向)

目录 一、WS前后移动 二、鼠标转向 一、WS前后移动 为了让玩家控制的“PlayerCharacter”能够实现前后移动 在“SCharacter.cpp"中添加如下代码 在“SCharacter.h"中添加如下代码 添加轴映射 设置自动控制玩家 此时按下WS键就可以前进后退了。 二、鼠标转向 …

2023年9月DAMA-CDGA/CDGP认证考试报名开始啦!

据DAMA中国官方网站消息&#xff0c;2023年度第三期DAMA中国CDGA和CDGP认证考试定于2023年9月23日举行。 报名通道现已开启&#xff0c;相关事宜通知如下&#xff1a; 考试科目: 数据治理工程师(CertifiedDataGovernanceAssociate,CDGA) 数据治理专家(CertifiedDataGovernanc…

SQL计算出每年在校人数

以下是一个录取学生人数表的示例&#xff0c;记录了每年录取学生的人数和入学学制。 idyearnumstu_len12018101322019121432020912420211513520211412620221613 字段解释&#xff1a; id&#xff1a;记录的唯一标识符year&#xff1a;学生入学年度num&#xff1a;对应年度录取…

计算机网络——三次握⼿、四次挥手

TCP 三次握手 1、第⼀个SYN报⽂&#xff1a; 客户端随机初始化序列号client_isn&#xff0c;放进TCP⾸部序列号段&#xff0c; 然后把SYN置1。把SYN报⽂发送给服务端&#xff0c;表⽰发起连接&#xff0c; 之后客户端处于SYN-SENT状态。 2、第⼆个报⽂SYNACK报⽂&#xff1a; …

文件IO_打开和关闭文件(附Linux-5.15.10内核源码分析)

目录 1.打开文件 1.1 函数原型介绍 1.1.1 open函数 1.1.2 creat函数 1.1.2 openat函数 1.2 内核源码分析 1.3 函数原型区别 2.关闭文件 2.1 函数原型介绍 2.1.1 close函数 2.2 内核源码实现 1.打开文件 1.1 函数原型介绍 1.1.1 open函数 #include <sys/types.…

【DC系列07】DC-7靶机复盘

【DC系列07】DC-7靶机复盘 这个靶机同样是直接给ip的 这个靶机在进入shell前是没有破绽的&#xff0c;并且进入主页面以后也并没有什么漏洞。如果不搜索一下这个靶机的解法很难去下一步操作。 在github.com上搜索dc7user然后选择code&#xff0c;里面可以找到dc7一个远程登陆…

WPS/Office Excel 方向键无法切换表格

问题&#xff1a;WPS/Office Excel 方向键无法切换表格。 分析&#xff1a;键盘开启了Scroll Lock&#xff0c;导致Excel开启了滚动锁定。滚动锁定如图: 解决&#xff1a;再次按下Scroll Lock键解锁即可。&#xff08;Scroll Lock键在键盘右侧上方。&#xff09;

CSS实现底部弧度效果

效果图如下 说明&#xff1a; 使用伪类处理&#xff0c;先将元素自身定位为relative; 伪类设置content:‘’&#xff0c;并相对定位为absolute&#xff0c;通过设置left ,top 值&#xff0c;改变width和和left来调节弧度。宽度需大于100%&#xff0c;将left设为&#xff08;100…

AWS 中文入门开发教学 48- S3 - 静态网站之王, 快速建立网站之首选

知识点 使用 S3 快速搭建静态网页网站使用 Route 53 服务解析网站域名实战演习 设计域名 Name: blog.deeplearnaws.ml建立同名的 S3 存储桶 上传网页文件到存储桶当中 ACL设置为所有人可读 设置存储桶为静态网站公开 进入属性,

索引相关操作

1、建立一个utf8编码的数据库test1 create database test1;2、建立商品表goods和栏目表category 按如下表结构创建表&#xff1a;存储引擎engine myisam 字符集charset utf8 mysql> desc goods;-------------------------------------------------------------| Field …

【试用科研好物】GPT辅助科研神器?AI助力科研?ChatPDF、有道速读

前言 近期需要阅读的论文很多&#xff0c;偶然间在微博刷到许多人推荐科研利器ChatPDF和有道速读。使用后的结论是不推荐使用&#xff0c;下面分别给出理由。 使用&评价 网页版&#xff0c;无需安装任何东西&#xff0c;两款都支持中文。 ChatPDF有道速读 下面太长不看…

vue项目优化问题

文章目录 1、常见的系统优化方案2、非常见的优化手段(但同样是很有用的)1、组件懒加载2、组件代码分割3、函数编译4、组件通讯 1、常见的系统优化方案 图片懒加载、图片压缩、路由组件按需加载(异步加载)、减少console、if判断、cdn加速、axios统一管理请求、v-if与v-show依据…

面试算法题—编程题2023

面试算法题—编程题2023 一、冒泡排序二、选择排序三、快速排序四、其它排序 最近在看一些面试题&#xff0c;发现很多面试过程中都会要求手写排序编程题&#xff0c;经过一番查找整理&#xff0c;可以快速学习和使用相关排序算法题&#xff0c;通俗易懂&#xff0c;手撕代码吊…

6月城市之星领跑活动获奖名单已出炉

经过一个月的角逐&#xff0c;6月城市之星领跑活动上榜名单终于出炉啦&#xff0c;本次城市赛道是根据最后登陆且6月份有入围博客之星用户的城市一共368个城市&#xff0c;城市人数划分区间具体情况如下&#xff1a; 200以上城市2个&#xff0c;其中有一些博主的城市由于未获取…