Kubernetes实战[2]: 服务发现机制与Cluster DNS的安装(无CA认证版)
服务发现机制
Kubernetes提供了两种发现Service的方法:
1.环境变量
当Pod运行的时候,Kubernetes会将之前存在的Service的信息通过环境变量写到Pod中。
这种方法要求Pod必须要在Service之后启动。
在Service之前启动的Pod就不会有该Service的环境变量。
采用DNS的方式就没有这个限制。
2.DNS
当有新的Service创建时,就会自动生成一条DNS记录。
使用这种方法,需要安装Cluster DNS。
在kubernetes中每一个service都会被分配一个虚拟IP,每一个Service在正常情况下都会长时间不会改变,这个相对于pod的不定IP,对于集群中APP的使用相对是稳定的。但是Service的信息注入到pod目前使用的是环境变量的方式,并且十分依赖于pod(rc)和service的创建顺序,这使得这个集群看起来又不那么完美,于是kubernetes以插件的方式引入了DNS系统,利用DNS对Service进行一个映射,这样我们在APP中直接使用域名进行引用,避免了之前的变量泛滥问题,也避免了创建顺序的尴尬局面。
Kubernetes1.2.7版本下Cluster DNS的安装
阅读github上官方源码发现:
Cluster DNS自Kubernetes1.3版本开始,结构发生了变化。这里先以1.2.7版本作为研究。
Cluster DNS扩展插件用于支持Kubernetes的服务发现机制,1.2.7版本中,Cluster DNS主要包含如下几项:
1)SkyDNS
提供DNS解析服务。
2)Etcd
用于DNS的存储。
3)Kube2sky
监听Kubernetes,当有新的Service创建时,将其注册到etcd上。
4)healthz
提供对skydns服务的健康检查功能。
在Master服务器上下载Kubernetes发布包
Cluster DNS在Kubernetes发布包的cluster/addons/dns目录下
[root@k8s-master home]# yum -y install wget [root@k8s-master home]# wget https://codeload.github.com/kubernetes/kubernetes/tar.gz/v1.2.7 [root@k8s-master home]# tar -xf kubernetes-1.2.7.tar.gz [root@k8s-master home]# ls kubernetes-1.2.7 kubernetes-1.2.7.tar.gz sheng [root@k8s-master home]# cd kubernetes-1.2.7/cluster/addons/dns [root@k8s-master dns]# ls kube2sky MAINTAINERS.md OWNERS README.md skydns skydns-rc.yaml.in skydns-svc.yaml.in #skydns-rc.yaml.in和skydns-svc.yaml.in是两个模板文件,通过设置的环境变量修改其中的相应属性值,可以生成Replication Controller和Service的定义文件。
需要注意,skydns服务使用的clusterIP需要我们指定一个固定的IP地址,每个Node的kubelet进程都将使用这个IP地址,不能通过Kuberneters自动给skydns分配。
通过环境变量,配置参数
[root@k8s-master dns]# vi ~/.bash_profile #添加下面三行
export DNS_SERVER_IP="10.254.10.2"
export DNS_DOMAIN="cluster.local"
export DNS_REPLICAS=1
设置 Cluster DNS Service的IP为 10.254.10.2(不能和已分配的IP重复,如10.0.10.0),Cluster DNS的本地域为 cluster.local。
修改每台Node上的kubelet启动参数
vim /etc/kubernetes/kubelet
在KUBELET_ARGS里增加:
--cluster_dns=10.254.10.2 --cluster_domain=cluster.local
即:
# Add your own!
KUBELET_ARGS="--cluster_dns=10.254.10.2 --cluster_domain=cluster.local"
cluster_dns为DNS服务的ClusterIP地址
cluster_domain为DNS服务中设置的域名
重启kubelet服务
systemctl restart kubelet
生成dns-rc.yaml和dns-svc.yaml
1. skydns配置文件
创建DNS服务的RC配置文件,在这个RC配置中包含了3个Container的定义
[root@k8s-master dns]# cat skydns-rc.yaml apiVersion: v1 kind: ReplicationController metadata:name: kube-dns-v9namespace: kube-systemlabels:k8s-app: kube-dnsversion: v9kubernetes.io/cluster-service: "true" spec:replicas: 1selector:k8s-app: kube-dnsversion: v9template:metadata:labels:k8s-app: kube-dnsversion: v9kubernetes.io/cluster-service: "true"spec:containers:- name: etcdimage: kube-registry:5000/etcdresources:limits:cpu: 100mmemory: 50Micommand:- /usr/local/bin/etcd- -data-dir- /var/etcd/data- -listen-client-urls- http://127.0.0.1:2379,http://127.0.0.1:4001- -advertise-client-urls- http://127.0.0.1:2379,http://127.0.0.1:4001- -initial-cluster-token- skydns-etcdvolumeMounts:- name: etcd-storagemountPath: /var/etcd/data- name: kube2skyimage: kube-registry:5000/kube2skyresources:limits:cpu: 100mmemory: 50Miargs:- -domain=cluster.local- -kube_master_url=http://10.0.0.11:8080- name: skydnsimage: kube-registry:5000/skydnsresources:limits:cpu: 100mmemory: 50Miargs:- -machines=http://localhost:4001- -addr=0.0.0.0:53- -domain=cluster.localports:- containerPort: 53name: dnsprotocol: UDP- containerPort: 53name: dns-tcpprotocol: TCPvolumes:- name: etcd-storageemptyDir: {}
(1)kube2sky容器需要访问Kubernetes Master,需要配置Master所在物理主机的IP地址和端口
(2)kube2sky容器和skydns容器的启动参数-domain,设置Kubernetes集群中Service所属的域名,本例中为cluster.local。启动后,kube2sky会监听Kubernetes,当有新的Service创建时,就会生成相应的记录并保存到etcd中。kube2sky为每个Service生成两条记录:
<service_name>.<namespace_name>.<domain> <service_name>.<namespace_name>.svc.<domain>
(3)skydns的启动参数-addr=0.0.0.0:53表示使用本机TCP和UDP的53端口提供服务。
创建DNS服务的Service配置文件如下:
[root@k8s-master dns]# cat skydns-svc.yaml apiVersion: v1 kind: Service metadata:name: kube-dnsnamespace: kube-systemlabels:k8s-app: kube-dnskubernetes.io/cluster-service: "true"kubernetes.io/name: "KubeDNS" spec:selector:k8s-app: kube-dns#clusterIP: {{ pillar['dns_server'] }} #<---添加DNS_SERVER_IPclusterIP: 10.254.10.2ports:- name: dnsport: 53protocol: UDP- name: dns-tcpport: 53protocol: TCP
注意:skydns服务使用的clusterIP需要我们指定一个固定的IP地址,每个Node的Kubelet进程都将使用这个IP地址,不能通过Kubernetes自动分配。
另外,这个IP地址需要在kube-apiserver启动参数–service-cluster-ip-range指定的IP地址范围内。
3. 创建skydns Pod和服务
通过kubectl create完成RC和Service的创建:
(1)通过定义文件dns-rc.yaml创建Cluster DNS Replication Controller
[root@k8s-master dns]# kubectl create -f skydns-rc.yaml replicationcontroller "kube-dns-v11" created
验证Cluster DNS Pod是否创建运行成功:
[root@k8s-master dns]# kubectl get pod --namespace=kube-system -o wide
NAME READY STATUS RESTARTS AGE IP NODE
kube-dns-v11-plw4m 0/4 ContainerCreating 0 9m <none> k8s-node-3
containercreating表示创建不成功
查看错误原因:
[root@k8s-master dns]# kubectl describe pod --namespace=kube-system Name: kube-dns-v11-3pln8 Namespace: kube-system Node: k8s-node-3/10.0.0.14 Start Time: Thu, 07 Jun 2018 22:02:39 +0800 Labels: k8s-app=kube-dnskubernetes.io/cluster-service=trueversion=v11 Status: Pending IP: Controllers: ReplicationController/kube-dns-v11 Containers:etcd:Container ID:Image: kube-registry:5000/etcdImage ID:Port:Command:/usr/local/bin/etcd-data-dir/var/etcd/data-listen-client-urlshttp://127.0.0.1:2379,http://127.0.0.1:4001-advertise-client-urlshttp://127.0.0.1:2379,http://127.0.0.1:4001-initial-cluster-tokenskydns-etcdLimits:cpu: 100mmemory: 500MiRequests:cpu: 100mmemory: 50MiState: WaitingReason: ContainerCreatingReady: FalseRestart Count: 0Volume Mounts:/var/etcd/data from etcd-storage (rw)Environment Variables: <none>kube2sky:Container ID:Image: kube-registry:5000/kube2skyImage ID:Port:Args:--domain=cluster.local--kube-master-url=http://10.0.0.11:8080Limits:cpu: 100mmemory: 200MiRequests:cpu: 100mmemory: 50MiState: WaitingReason: ContainerCreatingReady: FalseRestart Count: 0Liveness: http-get http://:8080/healthz delay=60s timeout=5s period=10s #success=1 #failure=5Readiness: http-get http://:8081/readiness delay=30s timeout=5s period=10s #success=1 #failure=3Volume Mounts: <none>Environment Variables: <none>skydns:Container ID:Image: kube-registry:5000/skydnsImage ID:Ports: 53/UDP, 53/TCPArgs:-machines=http://127.0.0.1:4001-addr=0.0.0.0:53-ns-rotate=false-domain=cluster.local.Limits:cpu: 100mmemory: 200MiRequests:cpu: 100mmemory: 50MiState: WaitingReason: ContainerCreatingReady: FalseRestart Count: 0Volume Mounts: <none>Environment Variables: <none>healthz:Container ID:Image: kube-registry:5000/exechealthzImage ID:Port: 8080/TCPArgs:-cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null-port=8080Limits:cpu: 10mmemory: 20MiRequests:cpu: 10mmemory: 20MiState: WaitingReason: ContainerCreatingReady: FalseRestart Count: 0Volume Mounts: <none>Environment Variables: <none> Conditions:Type StatusInitialized True Ready False PodScheduled True Volumes:etcd-storage:Type: EmptyDir (a temporary directory that shares a pod's lifetime)Medium: QoS Class: Burstable Tolerations: <none> Events:FirstSeen LastSeen Count From SubObjectPath Type Reason Message--------- -------- ----- ---- ------------- -------- ------ -------12h 2m 32 {kubelet k8s-node-3} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "POD" with ErrImagePull: "repository docker.io/kube-registry not found: does not exist or no pull access"12h 9s 532 {kubelet k8s-node-3} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "POD" with ImagePullBackOff: "Back-off pulling image \"kube-registry:5000\""
(2)生成Service的定义文件dns-svc.yaml创建Service
[root@k8s-master dns]# kubectl create -f skydns-svc.yaml service "kube-dns" created
[root@k8s-master dns]# kubectl get svc --namespace=kube-system -o wide NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kube-dns 10.254.10.2 <none> 53/UDP,53/TCP 9s k8s-app=kube-dns
[root@k8s-master dns]# kubectl create -f skydns-svc.yaml
The Service "kube-dns" is invalid: spec.clusterIP: Invalid value: "10.0.10.0": provided IP is not in the valid range
表示地址有冲突
创建完成后,查看到系统创建的RC、Pod和Service都已创建成功:
然后我们创建一个普通的Service,以redis-master服务为例:
[root@k8s-master home]# mkdir k8s_service [root@k8s-master home]# ls k8s_service kubernetes-1.2.7 kubernetes-1.2.7.tar.gz sheng [root@k8s-master home]# cd k8s_service/ [root@k8s-master k8s_service]# mkdir redis-yaml [root@k8s-master k8s_service]# cd redis-yaml/ [root@k8s-master redis-yaml]# vi redis-master-service.yaml apiVersion: v1 kind: Service metadata:name: redis-masterlabels:name: redis-master spec:selector:name: redis-masterports:- port: 6379targetPort: 6379 "redis-master-service.yaml" [New] 12L, 179C written
查看创建出来的Service:
[root@k8s-master redis-yaml]# kubectl create -f redis-master-service.yaml service "redis-master" created [root@k8s-master redis-yaml]# kubectl get service NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes 10.254.0.1 <none> 443/TCP 4d redis-master 10.254.195.220 <none> 6379/TCP 8s
4.Docker私有仓库搭建和使用
然后在10.0.0.10上创建Docker-registry 具体步骤详见: https://blog.51cto.com/sf1314/2124934
安装并启动docker(此步已安装忽略)
yum -y install docker systemctl start docker systemctl enable docker
搭建私有仓库
下载registry镜像
docker pull registry
防火墙添加运行5000端口
iptables -I INPUT 1 -p tcp --dport 5000 -j ACCEPT
下载完之后我们通过该镜像启动一个容器
docker run -d -p 5000:5000 --privileged=true -v /opt/registry:/tmp/registry registry
参数说明:
-v /opt/registry:/tmp/registry :默认情况下,会将仓库存放于容器内的/tmp/registry目录下,指定本地目录挂载到容器
–privileged=true :CentOS7中的安全模块selinux把权限禁掉了,参数给容器加特权,不加上传镜像会报权限错误(OSError: [Errno 13] Permission denied: ‘/tmp/registry/repositories/liibrary’)或者(Received unexpected HTTP status: 500 Internal Server Error)错误
检查5000端口
netstat -an | grep 5000
客户端上传镜像
修改/etc/sysconfig/docker(Ubuntu下配置文件地址为:/etc/init/docker.conf),增加启动选项(已有参数的在后面追加),之后重启docker,不添加报错,https证书问题。
OPTIONS='--insecure-registry kube-registry:5000'
#CentOS 7系统,注意如果是kube-registry:5000,则需要在/etc/hosts配置 10.0.0.10 kube-registry
# 后续拉取 10.0.0.10:5000需要docker pull 10.0.0.10:5000/centos1
# kube-registry:5000需要 docker pull docker-registry:5000/centos1
#other_args='--insecure-registry 10.0.0.10:5000' #CentOS 6系统
因为Docker从1.3.X之后,与docker registry交互默认使用的是https,而此处搭建的私有仓库只提供http服务
在docker公共仓库下载一个镜像
[root@etcd ~]# docker search pod-infrastructure INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED docker.io docker.io/openshift/origin-pod The pod infrastructure image for OpenShift 3 8 ...... [root@k8s-master ~]# docker search busybox INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED docker.io docker.io/busybox Busybox base image. 1272 [OK] ...... [root@etcd ~]# docker pull docker.io/openshift/origin-pod [root@etcd ~]# docker pull docker.io/busybox
来修改一下该镜像的tag
[root@etcd ~]# docker tag docker.io/openshift/origin-pod 10.0.0.10:5000/pod-infrastructure [root@etcd ~]# docker tag docker.io/busybox 10.0.0.10:5000/busybox
把打了tag的镜像上传到私有仓库
[root@etcd ~]# docker push 10.0.0.10:5000/pod-infrastructure [root@etcd ~]# docker push 10.0.0.10:5000/busybox
客户端添加私有仓库地址
# 添加这一行,修改/etc/sysconfig/docker文件,需要在/etc/hosts添加10.0.0.10 kube-registry解析并重新启动docker服务。
ADD_REGISTRY='--add-registry kube-registry:5000' systemctl restart docker
加上后,search镜像,私有仓库和docker hub上都会显示;
不加搜索私有仓库,需要命令中指定私有仓库ip
使用仓库中的镜像
[root@etcd ~]# curl http://10.0.0.10:5000/v2/_catalog {"repositories":["busybox","pod-infrastructure"]}
5. 通过DNS查找Service
使用一个带有nslookup工具的Pod来验证DNS服务是否能够正常工作:
[root@k8s-master ~]# cd /home [root@k8s-master home]# mkdir -p k8s_service/demo [root@k8s-master home]# cd k8s_service/demo [root@k8s-master demo]# cat busybox.yaml apiVersion: v1 kind: Pod metadata: name: busyboxnamespace: default spec:containers:- image: kube-registry:5000/busyboxcommand:- sleep- "3600"imagePullPolicy: IfNotPresentname: busyboxrestartPolicy: Always
运行kubectl create -f busybox.yaml完成创建。
[root@k8s-master demo]# kubectl create -f busybox.yaml pod "busybox" created
STATUS状态为Running则表示创建成功,若为ContainerCreating,则表示创建不成功
[root@k8s-master demo]# kubectl get pod NAME READY STATUS RESTARTS AGE busybox 1/1 Running 1 5m
例子:kubectl describe pod busybox可以查看部署失败的原因
[root@k8s-master demo]# kubectl describe pod busybox Name: busybox Namespace: default Node: k8s-node-1/10.0.0.12 Start Time: Thu, 07 Jun 2018 16:07:44 +0800 Labels: <none> Status: Pending IP: Controllers: <none> Containers:busybox:Container ID:Image: kube-registry:5000/busyboxImage ID:Port:Command:sleep3600State: WaitingReason: ContainerCreatingReady: FalseRestart Count: 0Volume Mounts: <none>Environment Variables: <none> Conditions:Type StatusInitialized True Ready False PodScheduled True No volumes. QoS Class: BestEffort Tolerations: <none> Events:FirstSeen LastSeen Count From SubObjectPath Type Reason Message--------- -------- ----- ---- ------------- -------- ------ -------20s 20s 1 {default-scheduler } Normal Scheduled Successfully assigned busybox to k8s-node-120s 9s 2 {kubelet k8s-node-1} Warning FailedSync Error syncing pod, skipping: failed to"StartContainer" for "POD" with ErrImagePull: "image pull failed for registry.access.redhat.com/rhel7/pod-infrastructure:latest, this may be because there are no credentials on this request. details: (open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory)"
在该容器成功启动后,通过kubectl exec nslookup 进行测试:
[root@docker1 demo]# kubectl exec busybox -- nslookup redis-master Server: 10.254.0.3 Address 1: 10.254.0.3 Name: redis-master Address 1: 10.254.7.16012345
可以看到,通过DNS服务器10.254.0.3成功找到了名为”redis-master”服务的IP地址:10.254.7.160
如果某个Service属于自定义的命名空间,那么进行Service查找时,需要带个namespace的名字。下面以查看kube-dns服务为例:
[root@docker1 demo]# kubectl exec busybox -- nslookup kube-dns.kube-systemServer: 10.254.0.3Address 1: 10.254.0.3Name: kube-dns.kube-system Address 1: 10.254.0.312345
如果仅使用”kube-dns”来进行查找,则将会失败:
nslookup: can’t resolve ‘kube-dns’
查看多个容器组成的Pod时,要添加-c选项指定容器的名称
# kubectl logs kube-dns-v9-curdr --namespace=kube-systemError from server: a container name must be specified for pod kube-dns-v9-curdr # kubectl logs kube-dns-v9-curdr -c skydns --namespace=kube-system123
5. DNS服务的工作原理解析
(1)kube2sky容器应用通过调用Kubernetes Master的API获得集群中所有Service的信息,并持续监控新Service的生成,然后定稿etcd中。
查看etcd存储的Service信息
# kubectl exec kube-dns-v9-evgl6 -c etcd --namespace=kube-system etcdctl ls /skydns/local/cluster/skydns/local/cluster/default/skydns/local/cluster/svc /skydns/local/cluster/kube-system1234
可以看到在skydns键下面,根据我们配置的域名(cluster.local)生成了local/cluster子键,接下来是namespace(default和kube-system)和svc(下面也按namespace生成子键)。
查看redis-master服务对应的键值:
# kubectl exec kube-dns-v9-evgl6 -c etcd --namespace=kube-system etcdctl get /skydns/local/cluster/default/redis-master {"host":"10.254.7.160","priority":10,"weight":10,"ttl":30,"targetstrip":0}12
可以看到,redis-master服务对应的完整域名为redis-master.default.cluster.local,并且其IP地址为10.254.7.160。
(2)根据Kubelet启动参数的设置(–cluster_dns),Kubelet会在每个新创建的Pod中设置DNS域名解析配置文件/etc/resolv.conf文件,在其中增加了一条nameserver配置和一条search配置:
nameserver 10.254.0.3nameserver 202.96.128.86search default.svc.cluster.local svc.cluster.local cluster.localoptions ndots:51234
通过名字服务器10.254.0.3访问的实际上是skydns在53端口上提供的DNS解析服务。
(3)应用程序就能够像访问网站域名一样,仅仅通过服务的名字就能访问到服务了。
例如,设置redis-slave的启动脚本为:
redis-server –slaveof redis-master 6379
创建redis-slave的Pod并启动它。
之后,我们可以登录redis-slave容器中查看,其通过DNS域名服务找到了redis-master的IP地址10.254.7.160,并成功建立了连接。
通过DNS设置,对于其他Service(服务)的查询将可以不再依赖系统为每个Pod创建的环境变量,而是直接使用Service的名字就能对其进行访问,使得应用程序中的代码更简洁了。
转载于:https://blog.51cto.com/sf1314/2124462
Kubernetes实战[2]: 服务发现机制与Cluster DNS的安装(无CA认证版)相关推荐
- 第四篇:服务发现机制
本文出自Service Discovery in a Microservices Architecture,作者 Chris Richardson, 写于2015年5月19日 这是本系列文章的第四篇. ...
- 微服务ServiceMesh及三种服务发现机制
1. 前言 今年,ServiceMesh(服务网格)概念在社区里头非常火,有人提出2018年是ServiceMesh年,还有人提出ServiceMesh是下一代的微服务架构基础.作为架构师,如果你现在 ...
- kubernetes上的服务发现-CoreDNS配置
参考: 官方网站,https://coredns.io/ CoreDNS安装,https://my.oschina.net/u/2306127/blog/1618543 CoreDNS使用手册,htt ...
- SPI(服务发现机制)
什么是SPI SPI ,全称为 Service Provider Interface,是一种服务发现机制.它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文 ...
- 从零开始入门 | Kubernetes 中的服务发现与负载均衡
作者 | 阿里巴巴技术专家 溪恒 一.需求来源 为什么需要服务发现 在 K8s 集群里面会通过 pod 去部署应用,与传统的应用部署不同,传统应用部署在给定的机器上面去部署,我们知道怎么去调用别的机 ...
- android module中获取 app_Android模块化中的服务发现机制
code小生 一个专注 Android 领域的技术平台 公众号回复 Android 加入我的安卓技术群 作者:低情商的大仙 链接:https://www.jianshu.com/p/de432a82e ...
- 一文了解 Kubernetes 中的服务发现
原文链接:一文了解 Kubernetes 中的服务发现 Kubernetes 服务发现是一个经常让我产生困惑的主题之一.本文分为两个部分: 网络方面的背景知识 深入了解 Kubernetes 服务发现 ...
- Kubernetes集群服务发现Service资源LoadBalancer类型详解(二十九)
Kubernetes集群服务发现Service资源LoadBalancer类型详解 1.LoadBalancer类型的service资源概念 LoadBalancer和Nodeport非常相似,目的都 ...
- 一文详解 Kubernetes 中的服务发现,运维请收藏
K8S 服务发现之旅 Kubernetes 服务发现是一个经常让我产生困惑的主题之一.本文分为两个部分: 网络方面的背景知识 深入了解 Kubernetes 服务发现 要了解服务发现,首先要了解背后的 ...
- 浅谈 Kubernetes 中的服务发现
原文:https://nigelpoulton.com/blog/f/demystifying-kubernetes-service-discovery Kubernetes 服务发现是一个经常让我产 ...
最新文章
- C#利用lambda在函数中创建内部函数
- 盘点丨机器学习2017年重大进展汇总
- 会话技术CookieSession
- fabric shim安装合约_智能合约简介_智能合约开发_Hyperledger Fabric_开发指南_区块链服务 BaaS - 阿里云...
- QML Profiler性能优化教程
- JAVA中用于处理字符串的 三兄弟
- C语言变量声明问题——变量定义一定要放在所有执行语句/语句块的最前面吗?
- Python爬虫 --- 2.2 Scrapy 选择器的介绍
- 音视频编解码:NVIDIA Jetson Linux Multimedia API(总结)
- HFSS脚本建模入门
- java生成mib文件_【snmp】使用MIB Builder生成MIB文件
- 车辆动力学知识总结(五)运动学模型的线性化和离散化
- 关于MATLAB调用第三方程序
- java中的String和ArrayList类
- 华人的旗帜——首位亚裔图灵奖获得者姚期智
- (摘之博客园狂奔di蜗牛)ASP.NET页面刷新方法总结
- 【轻博客观察之二】十问Tumblr
- Linux命令整理(二)
- dw选项卡代码_dreamweaver cs6快捷注释方法
- 游戏模拟器成了外挂帮凶,灰产对抗再升级
热门文章
- Android项目“error: Apostrophe not preceded by \ (”报错解决方法
- xlsx表格怎么做汇总统计_表格进行分类汇总怎么做
- ssh-keygen命令使用
- (2010计本3班-杨蒙)面向对象的C--实现链表操作
- Unity中访问GameCenter的实现
- WebForm CSS垂直虚线时间轴特效
- oracle的listener监听启动报TNS-12555/ TNS-12560 TNS-00525错误
- 阿里云ECS服务器修复漏洞
- OpenSSH 用户枚举漏洞(CVE-2018-15919)服务器修复方法(亲测实用)
- 外星人笔记本计算机在哪里,笔记本电脑没声音,详细教您外星人笔记本没声音如何解决...