商务服务
k8s实践(11) --服务发现CoreDNS和Kubernetes内部域名解析
2024-10-31 20:01

参考

k8s实践(11) --服务发现CoreDNS和Kubernetes内部域名解析

  • 官方网站,CoreDNS: DNS and Service Discovery
  • CoreDNS安装,https://my.oschina.net/u/2306127/blog/1618543
  • CoreDNS使用手册,CoreDNS: DNS and Service Discovery
  • CoreDNS源码,CoreDNS · GitHub
  • CoreDNS配置,https://my.oschina.net/u/2306127/blog/1788566

从Kubernetes 1.11开始,可使用CoreDNS作为Kubernetes的DNS插件进入GA状态,Kubernetes推荐使用CoreDNS作为集群内的DNS服务。 我们先看一下Kubernetes DNS服务的发展历程。

Kubernetes 1.3之前的版本使用skyDNS作为DNS服务,这个有点久远了。Kubernetes的DNS服务由kube2sky、skyDNS、etcd组成。 kube2sky通过kube-apiserver监听集群中Service的变化,将生成的DNS记录信息更新到etcd中,而skyDNS将从etcd中获取数据对外提供DNS的查询服务。

Kubernetes 1.3开始使用kubeDNS和dnsmasq替换了原来的kube2sky和skyDNS,不再使用etcd,而是将DNS记录直接存放在内存中,通过dnsmasq的缓存功能提高DNS的查询效率。下图是描述了Kubernetes使用kubeDNS实现服务发现的整体架构

从Kubernetes 1.11开始,可使用CoreDNS作为Kubernetes的DNS插件进入GA状态,Kubernetes推荐使用CoreDNS作为集群内的DNS服务。 CoreDNS从2017年初就成为了CNCF的的孵化项目,CoreDNS的特点就是十分灵活和可扩展的插件机制

各种插件实现

不同的功能,如重定向、定制DNS记录、记录日志等等。下图描述了CoreDNS的整体架构

     Kubernetes包括用于服务发现的DNS服务器Kube-DNS。 该DNS服务器利用SkyDNS的库来为Kubernetes pod和服务提供DNS请求。SkyDNS2的作者,Miek Gieben,创建了一个新的DNS服务器,CoreDNS,它采用更模块化,可扩展的框架构建。 Infoblox已经与Miek合作,将此DNS服务器作为Kube-DNS的替代品。

      CoreDNS利用作为Web服务器Caddy的一部分而开发的服务器框架。该框架具有非常灵活,可扩展的模型,用于通过各种中间件组件传递请求。这些中间件组件根据请求提供不同的操作,例如记录,重定向,修改或维护。虽然它一开始作为Web服务器,但是Caddy并不是专门针对HTTP协议的,而是构建了一个基于CoreDNS的理想框架。

      在这种灵活的模型中添加对Kubernetes的支持,相当于创建了一个Kubernetes中间件。该中间件使用Kubernetes API来满足针对特定Kubernetes pod或服务的DNS请求。而且由于Kube-DNS作为Kubernetes的另一项服务,kubelet和Kube-DNS之间没有紧密的绑定。您只需要将DNS服务的IP地址和域名传递给kubelet,而Kubernetes并不关心谁在实际处理该IP请求。

1.0.0版本主要遵循Kube-DNS的当前行为。 CoreDNS的005及更高版本实现了完整的规范和更多功能。

  • A记录(正常的Service分配了一个名为my-svc.my-namespace.svc.cluster.local的DNS A记录。 这解决了服务的集群IP
  • “headless”(没有集群IP)的Service也分配了一个名为my-svc.my-namespace.svc.cluster.local的DNS A记录。 与普通服务不同,这解决了Service选择了pods的一组IP。 客户预计将从这ip集合中消耗集合或使用标准循环选择。
  • 针对名为正常或无头服务的端口创建的SRV记录,对于每个命名的端口,SRV记录的格式为_my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster.local。对于常规服务,这将解析为端口号和CNAME:my-svc.my-namespace.svc.cluster.local;对于无头服务,这解决了多个答案,一个用于支持服务的每个pod,并包含端口号还有格式为auto-generated-name.my-svc.my-namespace.svc.cluster.local 的pod的CNAME 。SRV记录包含它们中的“svc”段,对于省略“svc”段的旧式CNAME不支持。
  • 作为Service一部分的endpoints的A记录(比如“pets”的记录
  • pod的Spec中描述的A记录
  • 还有就是用来发现正在使用的DNS模式版本的TXT记录

      所有群集中不需要pod A记录支持,默认情况下禁用。 此外,CoreDNS对此用例的支持超出了在Kube-DNS中找到的标准行为。

     在Kube-DNS中,这些记录不反映集群的状态,例如,对w-x-y-z.namespace.pod.cluster.local的任何查询将返回带有w.x.y.z(ip)的A记录,即使该IP不属于指定的命名空间,甚至不属于集群地址空间。最初的想法是启用对* .namespace.pod.cluster.local这样的域使用通配符SSL证书。

    CoreDNS集成了提供pod验证的选项,验证返回的IP地址w.x.y.z实际上是指定命名空间中的pod的IP。他防止在命名空间中欺骗DNS名称。 然而,它确实会大大增加CoreDNS实例的内存占用,因为现在它需要观察所有的pod,而不仅仅是服务端点。

2、架构

整个 CoreDNS 服务都建立在一个使用 Go 编写的 HTTP/2 Web 服务器 Caddy · GitHub 上,CoreDNS 整个项目可以作为一个 Caddy 的教科书用法。

CoreDNS 的大多数功能都是由插件来实现的,插件和服务本身都使用了 Caddy 提供的一些功能,所以项目本身也不是特别的复杂。

作为基于 Caddy 的 Web 服务器,CoreDNS 实现了一个插件链的架构,将很多 DNS 相关的逻辑都抽象成了一层一层的插件,包括 Kubernetes 等功能,每一个插件都是一个遵循如下协议的结构体

所以只需要为插件实现  以及  这两个接口并且写一些用于配置的代码就可以将插件集成到 CoreDNS 中。

另一个 CoreDNS 的特点就是它能够通过简单易懂的 DSL 定义 DNS 服务,在 Corefile 中就可以组合多个插件对外提供服务

对于以上的配置文件,CoreDNS 会根据每一个代码块前面的区和端点对外暴露两个端点提供服务

该配置文件对外暴露了两个 DNS 服务,其中一个监听在 5300 端口,另一个在 53 端口,请求这两个服务时会根据不同的域名选择不同区中的插件进行处理。

CoreDNS 可以通过四种方式对外直接提供 DNS 服务,分别是 UDP、gRPC、HTTPS 和 TLS

但是无论哪种类型的 DNS 服务,最终队会调用以下的  方法,为服务的调用者提供 DNS 服务

在上述这个已经被简化的复杂函数中,最重要的就是调用了『插件链』的  方法,将来源的请求交给一系列插件进行处理,如果我们使用以下的文件作为 Corefile

那么在 CoreDNS 服务启动时,对于当前的  这个组,它会依次加载 、、 和  几个插件,这里的顺序是由 zdirectives.go 文件定义的,启动的顺序是从下到上

因为启动的时候会按照从下到上的顺序依次『包装』每一个插件,所以在真正调用时就是从上到下执行的,这就是因为  方法中对插件进行了组合

对于 Corefile 里面的每一个配置组, 都会讲配置组中提及的插件按照一定的顺序组合起来,原理跟 Rack Middleware 的机制非常相似,插件  其实就是一个出入参数都是  的函数

所以我们可以将它们叠成堆栈的方式对它们进行操作,这样在最后就会形成一个插件的调用链,在每个插件执行方法时都可以通过  函数调用下一个插件的  方法

除了通过  调用下一个插件之外,我们也可以调用  方法并结束整个调用链。

从插件的堆叠到顺序调用以及错误处理,我们对 CoreDNS 的工作原理已经非常清楚了,接下来我们可以简单介绍几个插件的作用。

https://github.com/coredns/deployment/tree/master/kubernetes

注意和k8s的版本对应关系:https://github.com/coredns/deployment/blob/master/kubernetes/CoreDNS-k8s_version.md

主要有几个文件

      deploy.sh是一个便捷的脚本,用于生成用于在当前运行标准kube-dns的集群上运行CoreDNS的清单。使用coredns.yaml.sed文件作为模板,它创建一个ConfigMap和一个CoreDNS  deployment,然后更新 Kube-DNS service selector以使用CoreDNS deployment。 通过重新使用现有服务,服务请求不会中断。

    脚本不会删除kube-dns的deployment或replication controller - 您必须手动执行

kubectl delete --namespace=kube-system deployment kube-dns

要使用它,只需将它们放在同一目录中,然后运行deploy.sh脚本,将其传递给您的服务CIDR(10.3.0.0/24。 这将生成具有必要Corefile的ConfigMap。 它还将查找现有的kube-dns服务的集群IP。 

[root@k8s-master conf.d]# etcdctl ls /k8s/network/subnets
/k8s/network/subnets/10.0.24.0-24
/k8s/network/subnets/10.0.86.0-24
/k8s/network/subnets/10.0.35.0-24

(注意:以上原始脚本只适用于当前kubernetes集群含有kube-dns的情况,如果没有需要修改下脚本

10.0.24.200

默认情况下CLUSTER_DNS_IP是自动获取kube-dns的集群ip的,但是由于没有部署kube-dns所以只能手动指定一个集群ip了。

执行: https://blog.csdn.net/hguisu/article/details/deploy.sh 10.0.0.0/24 cluster.local 

以上脚本执行后可以看到预览的效果。

仔细观察上面的Corefile部分,这是一个在端口53上运行CoreDNS并为Kubernetes提供cluster.local域的示例

1)errors官方没有明确解释,后面研究

2)log stdout:日志中间件配置为将日志写入STDOUT

3)health:健康检查,提供了指定端口(默认为8080)上的HTTP端点,如果实例是健康的,则返回“OK”。

4)cluster.local:CoreDNS为kubernetes提供的域,10.3.0.0/24这告诉Kubernetes中间件它负责为反向区域提供PTR请求0.0.3.10.in-addr.arpa ..换句话说,这是允许反向DNS解析服务(我们经常使用到得DNS服务器里面有两个区域,即“正向查找区域”和“反向查找区域”,正向查找区域就是我们通常所说的域名解析,反向查找区域即是这里所说的IP反向解析,它的作用就是通过查询IP地址的PTR记录来得到该IP地址指向的域名,当然,要成功得到域名就必需要有该IP地址的PTR记录。PTR记录是邮件交换记录的一种,邮件交换记录中有A记录和PTR记录,A记录解析名字到地址,而PTR记录解析地址到名字。地址是指一个客户端的IP地址,名字是指一个客户的完全合格域名。通过对PTR记录的查询,达到反查的目的。

5)proxy:这可以配置多个upstream 域名服务器,也可以用于延迟查找 /etc/resolv.conf 中定义的域名服务器

6)cache:这允许缓存两个响应结果,一个是肯定结果(即,查询返回一个结果)和否定结果(查询返回“没有这样的域”,具有单独的高速缓存大小和TTLs。

#    https://blog.csdn.net/hguisu/article/details/deploy.sh -r 10.0.0.0/16 -i 192.168.10.90  -d cluster.local -t coredns.yaml.sed -s  > coredns.yaml

#   .kubectl apply -f coredns.yaml

或者直接执行

# https://blog.csdn.net/hguisu/article/details/deploy.sh -r 10.0.0.0/16 -i 192.168.10.90  -d cluster.local -t coredns.yaml.sed -s  | kubectl apply -f -

查看service

[root@k8s-master coredns]# kubectl get service -l k8s-app=kube-dns --namespace=kube-system
NAME       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   192.168.10.90   <none>        53/UDP,53/TCP,9153/TCP   15d

查看coredns的Pod,确认所有Pod都处于Running状态

方式一kubelet统一修改

kubelet的启动参数添加--cluster-dns配置:修改master节点和所有node节点--cluster-dns配置,修改内容如红色所注,与上面的Corefile中的值对应。

方式二:在pod启动添加

通过上述配置创建  之后,执行  命令即可看到额外的配置项目

即在 中多了 172.16.1.21、 中多了 和 两项值,及多了 配置。

因此,直接通过 进行配置后,默认是追加到当前默认配置中。

现在我们来创建一个wepapp的pod和service,测试一下coredns是否起作用

[root@k8s-master conf.d]# kubectl get pods  -o wide                           
NAME           READY     STATUS    RESTARTS   AGE       IP          NODE
webapp-nrz4t   1/1       Running   0          1d        10.0.35.3   192.168.10.39
webapp-zp69q   1/1       Running   0          1d        10.0.24.4   192.168.10.50

[root@k8s-master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   192.168.0.1      <none>        443/TCP    28d
webapp       ClusterIP   192.168.14.242   <none>        9081/TCP   17d
webapp2      ClusterIP   192.168.22.2     <none>        9082/TCP   17d

[root@k8s-master ~]# curl 192.168.22.2:9082
Hello world

1、检查集群的pod /etc/resolv.conf是否生效

首先进入这个集群内的另一个pod

kubectl exec -it webapp-nrz4t /bin/sh 或者 docker exec -it 0d0874df9e15 /bin/sh

$ cat /etc/resolv.conf

sh-4.2#  cat /etc/resolv.conf
nameserver 192.168.10.90
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

2、curl测试服务

3、在master的主机上修改 /etc/resolv.conf,增加一行:nameserver 192.168.10.90后执行

通过域名访问成功

我们在kubelet的启动参数添加--cluster-dns配置--cluster-dns=172.16.10.254。在Kubelet配置中通过使用–cluster-dns=10.10.10.2参数指定的coredns地址会被写入容器的/etc/resolv.conf配置中。

在 kubernetes 中还提供了 决定 内预设4种DNS策略:

None,无任何策略:表示空的DNS设置,这种方式一般用于想要自定义 DNS 配置的场景,往往需要和 dnsConfig 配合一起使用达到自定义 DNS 的目的。

Default,默认: 此种方式是让kubelet来决定使用何种DNS策略。而kubelet默认的方式,就是使用宿主机的/etc/resolv.conf文件。同时,kubelet也可以配置指定的DNS策略文件,使用kubelet参数即可,如:–resolv-conf=/etc/resolv.conf

ClusterFirst, 集群 DNS 优先:此种方式是使用kubernets集群内部中的kubedns或coredns服务进行域名解析。若解析不成功,才会使用宿主机的DNS配置来进行解析。

ClusterFistWithHostNet,集群 DNS 优先,并伴随着使用宿主机网络:在某些场景下,我们的 POD 是用 HOST 模式启动的(HOST模式,是共享宿主机网络的,一旦用 HOST 模式,表示这个 POD 中的所有容器,都要使用宿主机的 /etc/resolv.conf 配置进行DNS查询,但如果你想使用了 HOST 模式,还继续使用 Kubernetes 的DNS服务,那就将 dnsPolicy 设置为 ClusterFirstWithHostNet。

清除 Pod 预设 DNS 配置,当 dnsPolicy 设置成为这个值之后, kubernetes 不会为 Pod 预先加载任何逻辑用于判定得到 DNS 的配置。因此若将 dnsPolicy 设置为 None , 为了避免 Pod 里面没有 DNS 配置,最好通过 dnsConfig 来描述自定义的 DNS 参数。如下所示

Pod 里面的 DNS 配置继承了宿主机上的 DNS 配置。即,该 Pod 的 DNS 配置与宿主机完全一致。

查看到宿主机上的配置如下

通过上述配置创建 之后即可看到额外的配置项目,如下

注意:这个会覆盖--cluster-dns配置

与 Default 相反,会预先使用 (或 ) 的信息当预设置参数写入到该 Pod 内的DNS配置。

通过上述配置创建 之后,执行 springbootweb 命令即可看到额外的配置项目,如下

如设置了 时, 会被强制转化为 。如下

nameserver 172.16.1.21
nameserver 119.29.29.29

设置 之后,会让 Pod 与该节点公用相同的网络空间(网卡/路由等)

同时使用 与 作为 Pod 预设 DNS 配置。

1、CoreDNS ConfigMap选项

CoreDNS是一个模块化和可插拔的DNS服务器,每个插件都为CoreDNS添加了新功能。这可以通过维护Corefile来配置,Corefile是CoreDNS配置文件。集群管理员可以修改CoreDNS Corefile的ConfigMap以更改服务发现的工作方式。

在Kubernetes中,CoreDNS安装了以下默认的Corefile配置。先来看看默认的CoreDns的配置文件

kubectl edit configmap coredns -n kube-system, 红框部分是新加的

  • error: 错误记录到stdout
  • health:CoreDNS的运行状况报告为http:// localhost:8080 / health
  • kubernetes:CoreDNS将根据Kubernetes服务和pod的IP回复DNS查询
  • prometheus:CoreDNS的度量标准可以在http://localhost:9153/Prometheus格式的指标中找到
  • forward:任何不在Kubernetes集群域内的查询都将转发到预定义的解析器(/etc/resolv.conf
  • cache:启用前端缓存
  • loop:检测简单的转发循环,如果找到循环则停止CoreDNS进程
  • reload:允许自动重新加载已更改的Corefile。编辑ConfigMap配置后,请等待两分钟以使更改生效
  • loadbalance:这是一个循环DNS负载均衡器,可以在答案中随机化A,AAAA和MX记录的顺序

注意:CoreDNS 1.5.0以后不在使用proxy关键字,而是使用forward。

我们强制所有非集群 DNS 查找通过特定的域名服务器(位于172.16.1.21)来解析,将forward 指向域名服务器,而不是 /etc/resolv.conf。

如果域名后缀都为.xxxapi.com,并通过172.16.1.21域名服务器来解析

配置如下

   xxxapi.com:53 {
        errors
        cache 30
        forward . 172.16.1.21
 }

即上面截图。

然后可以访问进入容器:docker exec -it 7d9ba3b6acdf /bin/sh 可以ping通了

如果执行 nslookup 命令失败,检查如下内容

1、先检查本地 DNS 配置

查看配置文件 resolv.conf。

按照如下方法(注意搜索路径可能会因为云提供商不同而变化)验证搜索路径和 Name Server 的建立

nameserver 192.168.10.90
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

2、快速诊断

出现类似如下指示的错误,说明 kube-dns 插件或相关 Service 存在问题

检查service是否正常运行

kubectl get svc --namespace=kube-system

或者检查是否 DNS Pod 正在运行

使用 命令验证 DNS Pod 正在运行

kubectl get pods --namespace=kube-system -l k8s-app=kube-dns

应该能够看到类似如下信息

如果看到没有 Pod 运行,或 Pod 失败/结束,DNS 插件不能默认部署到当前的环境,必须手动部署。

或者查看service的Endpoint是否正常

kubectl get ep kube-dns --namespace=kube-system

如果没有看到 Endpoint,查看 调试 Service 文档 中的 Endpoint 段内容。

3、检查 DNS Pod 中的错误信息

使用 命令查看 DNS 后台进程的日志

看到错误信息

eflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Namespace: Get https://192.168.0.1:443/api/v1/namespace

2.168.0.1:443/api/v1/endpoints?limit=500&resourceVersion=0: x509: certificate is valid for 192.168.10.50, 10.0.0.1, not 192.168.0.1
E0710 16:00:58.986103       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Namespace: Get https://192.168.0.1:443/api/v1/namespaces?limit=500&resourceVersion=0: x509: certificate is valid for 192.168.10.50, 10.0.0.1, not 192.168.0.1
E0710 16:00:58.989633       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Service: Get https://192.168.0.1:443/api/v1/services?limit=500&resourceVersion=0: x509: certificate is valid for 192.168.10.50, 10.0.0.1, not 192.168.0.1
E0710 16:00:58.991655       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Endpoints: Get https://192.168.0.1:443/api/v1/endpoints?limit=500&resourceVersion=0: x509: certificate is valid for 192.168.10.50, 10.0.0.1, not 192.168.0.1
E0710 16:00:59.990732       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+inco

原因:192.168.0.1不在证书里面

解决:需要重新设置:apiserver证书

masterssl.cnf文件的示例如下:IP.3 = 192.168.0.1

[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster.local
IP.1 = ${K8S_SERVICE_IP}
IP.2 = ${MASTER_IPV4}

IP.3 = 192.168.0.1

错误信息
 


E0712 02:25:45.326123       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Service: Unauthorized
E0712 02:25:45.327038       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Endpoints: Unauthorized
E0712 02:25:45.328029       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Namespace: Unauthorized
E0712 02:25:46.327153       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Service: Unauthorized
E0712 02:25:46.328210       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Endpoints: Unauthorized
E0712 02:25:46.329160       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Namespace: Unauthorized
E0712 02:25:47.328243       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Service: Unauthorized
E0712 02:25:47.329143       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Endpoints: Unauthorized
E0712 02:25:47.330086       1 reflector.go:134] pkg/mod/k8s.io/client-go@v10.0.0+incompatible/tools/cache/reflector.go:95: Failed to list *v1.Namespace: Unauthorized

原因:service account 的token认知不通过,是因为重新生成证书后,需要删除旧的token。

解决

    以上就是本篇文章【k8s实践(11) --服务发现CoreDNS和Kubernetes内部域名解析】的全部内容了,欢迎阅览 ! 文章地址:http://dfvalve.xrbh.cn/news/923.html 
     资讯      企业新闻      行情      企业黄页      同类资讯      首页      网站地图      返回首页 迅博思语资讯移动站 http://keant.xrbh.cn/ , 查看更多   
最新新闻
云南网络营销软件哪个好?权威推荐助您快速选择
在数字化时代,网络营销软件成为了许多企业实现营销目标的重要工具。然而,市面上网络营销软件琳琅满目,选择一个适合自己的并不
宫崎骏的时代结束了
在《你想活出怎样的人生》之前,宫崎骏一直是著名的退休诈骗犯。七次退休又七次复出,年过八旬,创作欲还是旺盛到令人害怕。然而
个人大数据信用查询平台哪个更准确一些?蘑菇画像个人大数据信用报告查询平台更好用
个人大数据信用查询平台哪个更准确一些?蘑菇画像个人大数据信用报告查询平台更好用,个人大数据信用查询平台市面上还是比较多的
小红书关键词热度查询!国风大潮下,品牌怎么玩出花样、玩出水平?
国风,是当下年轻人钟爱的潮流。汉服穿搭、文物手办、国潮仿妆……频频出圈。“民族的就是世界的”,国风的影响力可谓深远,一说
app推广接单发布平台哪个好?怎么领取任务赚钱?
最近几年,随着互联网的快速发展,利用网络兼职的赚钱方式也呈现越来越火,非常受大众欢迎的趋势。而且其种类也非常多:微商、社
【可打印】文学常识常考100题汇总,初中生练一练!(部编版初中语文)
关注本公众号,私信发送数字:2493,领取电子打印版文学常识1、成语“万事俱备,只欠东风”是根据《三国演义》________ (战役)
“迎旅发大会 游美丽望城”望城首届文旅短视频大赛,最高3万奖励等你来拿!
湘江水浩浩奔腾,流淌沧桑巨变。铜官窑静穆肃然,在这里诉说着望城的厚重历史,流传着“君生我未生,我生君已老”凄美爱情故事;落日
mysql导入大txt文件怎么打开_mysql怎么导入txt文件?
有时候我们在使用mysql数据库的时候,想导入txt文本文档,要怎么操作呢?下面本篇文章就来给大家介绍一下方法
寸头抖音短视频教程_人开始衰老的迹象是什么
岁月不饶人,我才50出头,可是许多衰老迹象已经越来越明显,惹得中医闺蜜笑话这样的我。1、觉得右后背和肩膀疼,出现“五十肩”
什么是网站页脚:以及最佳页脚设计示例
主体内容外,网站还包括页眉和页脚,用于帮助访问者的特定目的。由于我们认为网站页脚设计同样重要,我们整理了10个最佳免费网站
本企业新闻

点击拨打: