【kubernetes学习】
k8s学习--安装
- 1、节点布局
- 2、所有节点安装dockers、kubeadm
- 2.1、安装docker
- 2.2、安装kubeadm
- 2.3、安装相关组件镜像
- 2.4、部署 Kubernetes 的 Master 节点
- 2.4.1、执行命令init
- 2.4.2、部署网络插件
- 2.5、加入node
- 3、部署dashboard
- 4、安装ceph
深入剖析kubernetes--ubuntu18.04安装kubuadm v1.17.2
1、节点布局
节点 | IP | name |
---|---|---|
master | 192.168.116.10 | k8s-master |
node | 192.168.116.11 | k8s-node1 |
node | 192.168.116.12 | k8s-node2 |
2、所有节点安装dockers、kubeadm
docker | 19.03.8 |
---|---|
kubernetes | v1.17.2 |
2.1、安装docker
root@k8s-master:~# cat docker_install.sh
#!/bin/bash
# step 1: 安装必要的一些系统工具
sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# step 2: 安装GPG证书
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# Step 3: 写入软件源信息
sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# Step 4: 更新并安装Docker-CE
sudo apt-get -y update
sudo apt-get -y install docker-ce=5:19.03.8~3-0~ubuntu-bionic
2.2、安装kubeadm
由于有网络原因,使用阿里云仓库安装
root@k8s-master:~# cat kube_install.sh
#!/bin/bash
apt-get update && apt-get install -y apt-transport-https
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
echo "deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" >/etc/apt/sources.list.d/kubernetes.list
apt-get update
apt-get install -y kubeadm=1.17.2-00 关闭swap
swapoff -a
2.3、安装相关组件镜像
root@k8s-master:~# kubeadm config images list --kubernetes-version v1.17.2
k8s.gcr.io/kube-apiserver:v1.17.2
k8s.gcr.io/kube-controller-manager:v1.17.2
k8s.gcr.io/kube-scheduler:v1.17.2
k8s.gcr.io/kube-proxy:v1.17.2
k8s.gcr.io/pause:3.1
k8s.gcr.io/etcd:3.4.3-0
k8s.gcr.io/coredns:1.6.5
#镜像在国外,先下载阿里云镜像,否则速度慢;不下载初始化时会自动从国外下载
root@k8s-master:~# cat images-download.sh
#!/bin/bash
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.17.2
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:v1.17.2
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.17.2
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.17.2
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.1
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.4.3-0
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:1.6.5
2.4、部署 Kubernetes 的 Master 节点
root@k8s-master:~# cat kubeadm.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
controllerManager:extraArgs:horizontal-pod-autoscaler-use-rest-clients: "true" #将来部署的 kube-controller-manager 能够使用自定义资源(Custom Metrics)进行自动水平扩展horizontal-pod-autoscaler-sync-period: "10s"node-monitor-grace-period: "10s"
apiServer:extraArgs:runtime-config: "api/all=true"
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers #指定镜像仓库
kubernetesVersion: "v1.17.2"
2.4.1、执行命令init
由于现在kubelet版本过低,最近版为1.23.1,会报错,需要加上–ignore-preflight-errors=KubeletVersion
root@k8s-master:~# kubeadm init --config kubeadm.yaml --ignore-preflight-errors=KubeletVersionYour Kubernetes control-plane has initialized successfully!
#第一次使用 Kubernetes 集群所需要的配置命令To start using your cluster, you need to run the following as a regular user:mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/configYou should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:https://kubernetes.io/docs/concepts/cluster-administration/addons/#给这个 Master 节点添加更多工作节点(Worker)的命令
Then you can join any number of worker nodes by running the following on each as root:kubeadm join 192.168.116.10:6443 --token to3e1z.tl35kwpru8nfxime \--discovery-token-ca-cert-hash sha256:a898144fe8f9ff74c338b8e2ed133efa50527e3ed59be881acda57e38d01e645
查看当前节点状态
root@k8s-master:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master NotReady master 11h v1.23.1
通过 kubectl describe 指令的输出,我们可以看到 NodeNotReady 的原因在于,我们尚未部署任何网络插件
root@k8s-master:~# kubectl describe nodes k8s-master
Conditions:Type Status LastHeartbeatTime LastTransitionTime Reason Message---- ------ ----------------- ------------------ ------ Ready False Sat, 25 Dec 2021 09:07:10 +0800 Sat, 25 Dec 2021 09:07:10 +0800 KubeletNotReady container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
另外,我们还可以通过 kubectl 检查这个节点上各个系统 Pod 的状态,其中,kube-system 是 Kubernetes 项目预留的系统 Pod 的工作空间(Namepsace,注意它并不是 Linux Namespace,它只是 Kubernetes 划分不同工作空间的单位)
root@k8s-master:~# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-7f9c544f75-9tjds 0/1 Pending 0 11h
coredns-7f9c544f75-k89sw 0/1 Pending 0 11h
etcd-k8s-master 1/1 Running 1 11h
kube-apiserver-k8s-master 1/1 Running 1 11h
kube-controller-manager-k8s-master 1/1 Running 1 11h
kube-proxy-ffwmv 1/1 Running 1 11h
kube-scheduler-k8s-master 1/1 Running 1 11h
可以看到,CoreDNS、kube-controller-manager 等依赖于网络的 Pod 都处于 Pending 状态,即调度失败。这当然是符合预期的:因为这个 Master 节点的网络尚未就绪
2.4.2、部署网络插件
root@k8s-master:~# kubectl apply -f https://cloud.weave.works/k8s/net?k8s-version=v1.17.2#或者使用kubectl apply -n kube-system -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"#需要部署node节点后显示正常
root@k8s-master:~# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-7f9c544f75-9tjds 1/1 Running 0 11h
coredns-7f9c544f75-k89sw 1/1 Running 0 11h
etcd-k8s-master 1/1 Running 1 11h
kube-apiserver-k8s-master 1/1 Running 1 11h
kube-controller-manager-k8s-master 1/1 Running 1 11h
kube-proxy-ffwmv 1/1 Running 1 11h
kube-proxy-phtzj 1/1 Running 0 7m59s
kube-proxy-vwpdk 1/1 Running 0 8m10s
kube-scheduler-k8s-master 1/1 Running 1 11h
weave-net-dq5ft 2/2 Running 0 12m
weave-net-pxdbl 2/2 Running 0 8m10s
weave-net-xs4bc 2/2 Running 0 7m59sroot@k8s-master:~# kubectl get pod -A -o wide 显示详细信息
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system coredns-7f9c544f75-9tjds 1/1 Running 0 12h 10.40.0.1 k8s-master <none> <none>
kube-system coredns-7f9c544f75-k89sw 1/1 Running 0 12h 10.40.0.2 k8s-master <none> <none>
kube-system etcd-k8s-master 1/1 Running 1 12h 192.168.116.10 k8s-master <none> <none>
kube-system kube-apiserver-k8s-master 1/1 Running 1 12h 192.168.116.10 k8s-master <none> <none>
kube-system kube-controller-manager-k8s-master 1/1 Running 1 12h 192.168.116.10 k8s-master <none> <none>
kube-system kube-proxy-ffwmv 1/1 Running 1 12h 192.168.116.10 k8s-master <none> <none>
kube-system kube-proxy-phtzj 1/1 Running 0 29m 192.168.116.11 k8s-node1 <none> <none>
kube-system kube-proxy-vwpdk 1/1 Running 0 30m 192.168.116.12 k8s-node2 <none> <none>
kube-system kube-scheduler-k8s-master 1/1 Running 1 12h 192.168.116.10 k8s-master <none> <none>
kube-system weave-net-dq5ft 2/2 Running 0 34m 192.168.116.10 k8s-master <none> <none>
kube-system weave-net-pxdbl 2/2 Running 0 30m 192.168.116.12 k8s-node2 <none> <none>
kube-system weave-net-xs4bc 2/2 Running 0 29m 192.168.116.11 k8s-node1 <none> <none>
2.5、加入node
Kubernetes 的 Worker 节点跟 Master 节点几乎是相同的,它们运行着的都是一个 kubelet 组件。唯一的区别在于,在 kubeadm init 的过程中,kubelet 启动后,Master 节点上还会自动运行 kube-apiserver、kube-scheduler、kube-controller-manger 这三个系统 Pod。
所以,相比之下,部署 Worker 节点反而是最简单的,只需要两步即可完成。
第一步,在所有 Worker 节点上执行“安装 kubeadm 和 Docker”一节的所有步骤。
第二步,执行部署 Master 节点时生成的 kubeadm join 指令:
root@k8s-node2:~# kubeadm join 192.168.116.10:6443 --token to3e1z.tl35kwpru8nfxime \
> --discovery-token-ca-cert-hash sha256:a898144fe8f9ff74c338b8e2ed133efa50527e3ed59be881acda57e38d01e645
通过 Taint/Toleration 调整 Master 执行 Pod 的策略
root@k8s-master:~# kubectl taint nodes k8s-master foo=bar:NoSchedule
node/k8s-master tainted
我们只要在 Pod 的.yaml 文件中的 spec 部分,加入 tolerations 字段即可:
apiVersion: v1
kind: Pod
...
spec:tolerations:- key: "foo"operator: "Equal"value: "bar"effect: "NoSchedule"
现在回到我们已经搭建的集群上来。这时,如果你通过 kubectl describe 检查一下 Master 节点的 Taint 字段,就会有所发现了:
Taints: foo=bar:NoSchedulenode-role.kubernetes.io/master:NoSchedule
当然,如果你就是想要一个单节点的 Kubernetes,删除这个 Taint 才是正确的选择
root@k8s-master:~# kubectl taint nodes --all node-role.kubernetes.io/master-
node/k8s-master untainted
taint "node-role.kubernetes.io/master" not found
taint "node-role.kubernetes.io/master" not found
3、部署dashboard
root@k8s-master:~# kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc6/aio/deploy/recommended.yaml
#由于下载不了,可以浏览其打开保存文件
root@k8s-master:~# vim recommended.yaml
root@k8s-master:~# kubectl apply -f recommended.yaml root@k8s-master:~# kubectl get pods -n kubernetes-dashboard
NAME READY STATUS RESTARTS AGE
dashboard-metrics-scraper-7b8b58dc8b-7zlb7 1/1 Running 0 6m2s
kubernetes-dashboard-5f5f847d57-gt5tn 1/1 Running 0 6m2s
4、安装ceph
rook使用存储方式
rook默认使用所有节点的所有资源,rook operator自动在所有节点上启动OSD设备,Rook会用如下标准监控并发现可用设备:
设备没有分区
设备没有格式化的文件系统
Rook不会使用不满足以上标准的设备。另外也可以通过修改配置文件,指定哪些节点或者设备会被使用。
#添加新磁盘
root@k8s-master:~# for host in $(ls /sys/class/scsi_host) ; do echo "- - -" > /sys/class/scsi_host/$host/scan ; done
安装
https://github.com/rook/rook/blob/master/Documentation/quickstart.md查看安装说明
$ git clone --single-branch --branch {{ branchName }} https://github.com/rook/rook.git
cd rook/deploy/examples
kubectl create -f crds.yaml -f common.yaml -f operator.yaml
kubectl create -f cluster.yaml
root@k8s-master:~# git clone --single-branch --branch v1.6.3 https://github.com/rook/rook.git
root@k8s-master:~# cd rook/deploy/examples
root@k8s-master:~/rook/deploy/examples# kubectl create -f crds.yaml -f common.yaml -f operator.yaml
root@k8s-master:~/rook/deploy/examples# kubectl create -f cluster.yaml
#可以查看正在创建的pod
root@k8s-master:~/rook/deploy/examples# kubectl -n rook-ceph get pod
NAME READY STATUS RESTARTS AGE
csi-cephfsplugin-6vfjn 2/3 ImagePullBackOff 0 61s
csi-cephfsplugin-b5srz 0/3 ContainerCreating 0 61s
csi-cephfsplugin-pkhcq 0/3 ContainerCreating 0 61s
csi-cephfsplugin-provisioner-8684d87467-x5lzv 0/6 ContainerCreating 0 61s
csi-cephfsplugin-provisioner-8684d87467-xxpgw 0/6 ContainerCreating 0 61s
csi-rbdplugin-dxlzl 0/3 ContainerCreating 0 61s
csi-rbdplugin-l7fjn 0/3 ContainerCreating 0 61s
csi-rbdplugin-provisioner-6b97cb8965-mjk75 0/6 ContainerCreating 0 61s
csi-rbdplugin-provisioner-6b97cb8965-szw42 0/6 ContainerCreating 0 61s
csi-rbdplugin-w946b 2/3 ImagePullBackOff 0 61s
rook-ceph-detect-version-qrkt4 0/1 PodInitializing 0 2m36s
rook-ceph-operator-df47484f5-pwlzb 1/1 Running 0 3m13s#由于部分镜像下载不了,可以在阿里云下载,在打tag
root@k8s-master:~/rook/deploy/examples# docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/csi-node-driver-registrar:v2.3.0
root@k8s-master:~/rook/deploy/examples# docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/csi-node-driver-registrar:v2.3.0 k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.3.0#若打tag不行,可更换仓库源(生产环境最好更好为公司仓库)
root@k8s-master:~/rook/deploy/examples# vim operator.yaml ROOK_CSI_REGISTRAR_IMAGE: "registry.cn-hangzhou.aliyuncs.com/google_containers/csi-node-driver-registrar:v2.3.0"ROOK_CSI_RESIZER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/google_containers/csi-resizer:v1.3.0"ROOK_CSI_PROVISIONER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/google_containers/csi-provisioner:v3.0.0"ROOK_CSI_SNAPSHOTTER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/google_containers/csi-snapshotter:v4.2.0"ROOK_CSI_ATTACHER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/google_containers/csi-attacher:v3.3.0"
root@k8s-master:~/rook/deploy/examples# kubectl apply -f operator.yaml
若需要删除namespace,强制删除也不行,可使用一下方式
root@k8s-master:~/rook/deploy/examples# kubectl get ns
NAME STATUS AGE
default Active 21h
kube-node-lease Active 21h
kube-public Active 21h
kube-system Active 21h
kubernetes-dashboard Active 9h
rook-ceph Terminating 7h #此种状态强制删除也不行kubectl delete -n rook-ceph --force
https://github.com/g114486803g/jsj/blob/master/kill-namespace.sh
#!/bin/bashset -eo pipefaildie() { echo "$*" 1>&2 ; exit 1; }need() {which "$1" &>/dev/null || die "Binary '$1' is missing but required"
}# checking pre-reqsneed "jq"
need "curl"
need "kubectl"PROJECT="$1"
shifttest -n "$PROJECT" || die "Missing arguments: kill-ns <namespace>"kubectl proxy &>/dev/null &
PROXY_PID=$!
killproxy () {kill $PROXY_PID
}
trap killproxy EXITsleep 1 # give the proxy a secondkubectl get namespace "$PROJECT" -o json | jq 'del(.spec.finalizers[] | select("kubernetes"))' | curl -s -k -H "Content-Type: application/json" -X PUT -o /dev/null --data-binary @- http://localhost:8001/api/v1/namespaces/$PROJECT/finalize && echo "Killed namespace: $PROJECT"
#删除不掉跟finalizers有关
root@k8s-master:~/rook/deploy/examples# kubectl edit ns rook-ceph
spec:finalizers:- kubernetesroot@k8s-master:~/rook/deploy/examples# bash namespace.sh rook-ceph
Killed namespace: rook-ceph
root@k8s-master:~/rook/deploy/examples# kubectl get ns #删除啦
NAME STATUS AGE
default Active 21h
kube-node-lease Active 21h
kube-public Active 21h
kube-system Active 21h
kubernetes-dashboard Active 9h
安装完成后
root@k8s-master:~/rook/deploy/examples# kubectl get pod -n rook-ceph
NAME READY STATUS RESTARTS AGE
csi-cephfsplugin-h8h2x 3/3 Running 0 9m57s
csi-cephfsplugin-nhrkp 3/3 Running 0 10m
csi-cephfsplugin-provisioner-c4cdb4447-6jcsb 6/6 Running 0 10m
csi-cephfsplugin-provisioner-c4cdb4447-x2lck 6/6 Running 0 10m
csi-cephfsplugin-wgl4f 3/3 Running 0 10m
csi-rbdplugin-7c52g 3/3 Running 0 10m
csi-rbdplugin-l5bzf 3/3 Running 0 10m
csi-rbdplugin-provisioner-6897568457-dpwwb 6/6 Running 0 10m
csi-rbdplugin-provisioner-6897568457-lw6zf 6/6 Running 0 10m
csi-rbdplugin-q8zm6 3/3 Running 0 10m
rook-ceph-crashcollector-k8s-master-5d56f9c8f-nm4gv 1/1 Running 0 9m51s
rook-ceph-crashcollector-k8s-node1-7fdf6884db-sr96x 1/1 Running 0 26m
rook-ceph-crashcollector-k8s-node2-7d6c44f7dd-974wb 1/1 Running 0 9m57s
rook-ceph-mgr-a-58f55d947d-csp82 1/1 Running 0 9m57s
rook-ceph-mon-a-5747876b9d-rsz8l 1/1 Running 0 32m
rook-ceph-mon-c-7c6bb588df-46std 1/1 Running 0 29m
rook-ceph-mon-d-d4bcc8f47-sx2pq 1/1 Running 0 25m
rook-ceph-operator-df47484f5-qjntw 1/1 Running 0 36m
rook-ceph-osd-prepare-k8s-master-dpc6s 0/1 Completed 0 24m
rook-ceph-osd-prepare-k8s-node1-xqlnw 0/1 Completed 0 23m
rook-ceph-osd-prepare-k8s-node2-btrfz 0/1 Completed 0 23m
ceph挂载空分区、无文件系统
root@k8s-master:~/rook/deploy/examples# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 100G 0 disk
└─sda1 8:1 0 100G 0 part /
sdb 8:16 0 200G 0 disk
└─ceph--6f1ab381--6496--4981--b139--9bf6be7f4d56-osd--block--d8c9f3c3--cf24--4035--8fc5--e9bb46244364 253:0 0 200G 0 lvm
sr0 11:0 1 1024M 0 rom
【kubernetes学习】相关推荐
- Kubernetes学习笔记三:Docker安装,Docker使用,编写Dockerfile,制作容器镜像,上传docker镜像
文章目录 Docker的安装 Docker的使用:docker run命令 查看本地存在的镜像:docker images命令 编写Dockerfile,制作容器镜像 docker build制作镜像 ...
- Kubernetes学习笔记二:Namespace,Cgroups 的隔离与应用
Kubernetes学习系列文章:Kubernetes-博客专栏 今天在学习极客时间专栏:<深入剖析Kubernetes> 第五讲05 | 白话容器基础(一):从进程说开去和第六讲06 | ...
- Kubernetes学习笔记一:Docker和Kubernetes的诞生
Kubernetes学习系列文章:Kubernetes-博客专栏 今天在学习极客时间专栏:<深入剖析Kubernetes> 里面的01 | 预习篇 · 小鲸鱼大事记(一):初出茅庐到04 ...
- Kubernetes学习笔记(一)
2019独角兽企业重金招聘Python工程师标准>>> Kubernetes学习笔记(一) 博客分类: Kubernetes 导语 2015年4月,传闻已久的Borg论文伴随Kube ...
- kubernetes学习笔记 (二):k8s初体验
本文采用本地k8s v1.10.3版本开发,如果还没有搭建可参照 kubernetes学习笔记 (一):搭建本地k8s开发环境进行搭建 搭建本地Docker镜像仓库 docker pull docke ...
- Kubernetes学习笔记之Calico CNI Plugin源码解析(一)
女主宣言 今天小编为大家分享Kubernets Calico CNI Plugin的源码学习笔记,希望对正在学习k8s相关部分的同学有所帮助: PS:丰富的一线技术.多元化的表现形式,尽在" ...
- Kubernetes 学习总结(19)—— Kubernetes 集群管理平台如何选择?Rancher vs KubeSphere
前言 Kubernetes(K8s)集群管理平台都是基于 Kubernetes 提供功能,可以说他们是在 K8s 的基础上封装了一层更为友好的操作方式.他们都是为了降低 k8s 集群运维复杂度,降低运 ...
- Kubernetes学习总结(16)—— Kubernetes 实战之部署 Redis 集群
一.问题分析 本质上来说在 k8s 上部署一个 redis 集群和部署一个普通应用没有什么太大的区别,但需要注意下面几个问题: Redis 是一个有状态应用:这是部署 redis 集群时我们最需要注意 ...
- Kubernetes学习之路目录
Kubernetes基础篇 环境说明 版本说明 系统环境 Centos 7.2 Kubernetes版本 v1.11.2 Docker版本 v18.09 Kubernetes学习之路(一)之概念和架构 ...
- Kubernetes学习-K8S安装篇-Kubeadm安装高可用K8S集群
Kubernetes学习-K8S安装篇-Kubeadm高可用安装K8S集群 1. Kubernetes 高可用安装 1.1 kubeadm高可用安装k8s集群1.23.1 1.1.1 基本环境配置 1 ...
最新文章
- TiM:rDNA拷贝数的种内变化影响微生物群落分析吗?
- 基本数据类型与引用数据类型的不同
- java中交通灯管理系统_java案例--交通灯管理系统学习
- PAT-1127. ZigZagging on a Tree (30)
- MFC制作打地鼠小游戏
- 个人笔记 vue npm redis
- 关于layui.laypage.render 刷新首页没有分页问题
- php更新用户数据为空,php - 使用PHP更新数据库,而没有来自HTML表单的空值 - SO中文参考 - www.soinside.com...
- FastFDS--文件服务系统
- 计算机软件的英文简称,计算机常见英文缩写.docx
- java爬虫爬取b站视频分享iframe代码并保存10000条数据到数据库
- macOS 升级12.6后 Electron 应用闪退
- iso国家代码 三位字母_ISO 2字母语言代码
- Marvell宣战博通网络交换芯片,一大波饿狼扑食而来
- 再见了繁琐的Excel,掌握数据分析处理技术就靠它了
- GoogleChromePortable 谷歌chrome浏览器便携版官网下载方式
- 在线IDE- Gitpod介绍
- FCPX插件:专业分级调色插件ColorFinale Pro
- WebStorm高效快捷生成html标签锦集(IDEA同)
- 安徽全省谷歌卫星地图免费下载的方法