LocalDNS
目录
文章目录
- 目录
- 本节实战
- DNS优化
- 1、dns 5s 超时问题
- 解决办法
- 2、NodeLocal DNSCache
- 实验软件
- 关于我
- 最后
本节实战
实战名称 |
---|
💘 实战:NodeLocal DNSCache-2022.7.30(测试成功) |
💘 实战:NodeLocal DNSCache-2023.2.21(测试成功) |
DNS优化
前面我们讲解了在 Kubernetes 中我们可以使用 CoreDNS 来进行集群的域名解析,但是如果在集群规模较大并发较高的情况下我们仍然需要对 DNS 进行优化,典型的就是大家比较熟悉的 CoreDNS 会出现超时5s的情况。
1、dns 5s 超时问题
DNS 解析出现的 5s 超时的问题,并不是 Kubernertes 的问题,而是 conntrack 的一个 bug,也就是连接跟踪表。Weave works 的工程师 Martynas Pumputis 对这个问题做了很详细的分析:https://www.weave.works/blog/racy-conntrack-and-dns-lookup-timeouts。由于 conntrack 涉及到内核的一些知识,这里我们也不用太深入了,感兴趣的可以自行去了解,可以参考文章
https://opengers.github.io/openstack/openstack-base-netfilter-framework-overview/ 进行更多了解。
以上2篇文章已下载到本地:
Racy conntrack and DNS lookup timeouts-2023.2.19-剪藏
云计算底层技术 - netfilter 框架研究 _ opengers-2023.2.19-剪藏
我们简单总结下:当加载内核模块 nf_conntrack 后,conntrack 机制就开始工作,对于每个通过 conntrack 的数据包,内核都为其生成一个 conntrack 条目用以跟踪此连接,对于后续通过的数据包,内核会判断若此数据包属于一个已有的连接,则更新所对应的 conntrack 条目的状态(比如更新为 ESTABLISHED 状态),否则内核会为它新建一个conntrack 条目。所有的 conntrack 条目都存放在一张表里,称为连接跟踪表。连接跟踪表存放于系统内存中,可以用cat /proc/net/nf_conntrack
查看当前跟踪的所有 conntrack 条目(Ubuntu 则是 conntrack 命令)。
而出现该问题的根源在于 DNS 客户端( glibc 或 musl libc )会并发请求 A(ipv4 地址)和 AAAA(ipv6 地址)记录,跟 DNS Server 通信自然会先 connect 建立 fd,后面请求报文使用这个 fd 来发送,由于 UDP 是无状态协议,connect 时并不会创建 conntrack 表项, 而并发请求的 A 和 AAAA 记录默认使用同一个 fd 发包,这时它们源Port 相同,当并发发包时,两个包都还没有被插入 conntrack 表项,所以 netfilter 会为它们分别创建conntrack 表项,而集群内请求 kube-dns 都是访问的 Cluster-IP,报文最终会被 DNAT 成一个 endpoint 的Pod IP,当两个包被 DNAT 成同一个 IP,最终它们的五元组就相同了,在最终插入的时候后面那个包就会被丢掉,如果dns 的 pod 副本只有一个实例的情况就很容易发生,现象就是 dns 请求超时,client 默认策略是等待 5s 自动重试,如果重试成功,我们看到的现象就是 dns 请求有 5s 的延时。
netfilter conntrack 模块为每个连接创建 conntrack 表项时,表项的创建和最终插入之间还有一段逻辑,没有加锁,是一种乐观锁的过程。conntrack 表项并发刚创建时五元组不冲突的话可以创建成功,但中间经过 NAT 转换之后五元组就可能变成相同,第一个可以插入成功,后面的就会插入失败,因为已经有相同的表项存在。比如一个 SYN 已经做了NAT 但是还没到最终插入的时候,另一个 SYN 也在做 NAT,因为之前那个 SYN 还没插入,这个 SYN 做 NAT 的时候就认为这个五元组没有被占用,那么它 NAT 之后的五元组就可能跟那个还没插入的包相同。
所以总结来说,根本原因是内核 conntrack 模块的 bug,**DNS client(在 linux 上一般就是 上一般就是 resolver)**会并发地请求 A 和 AAAA 记录,netfilter 做 NAT 时可能发生资源竞争导致部分报文丢弃。
- 只有多个线程或进程,并发从同一个 socket 发送相同五元组的 UDP 报文时,才有一定概率会发生
- glibc、musl(alpine 的 libc 库)都使用 parallel query ,就是并发发出多个查询请求,因此很容易碰到这样的冲突,造成查询请求被丢弃
- 由于 ipvs 也使用了 conntrack, 使用 kube-proxy 的 ipvs 模式,并不能避免这个问题
解决办法
要彻底解决这个问题最好当然是内核上去 FIX 掉这个 BUG,除了这种方法之外我们还可以使用其他方法来进行规避,我们可以避免相同五元组 DNS请求的并发。
在 resolv.conf
中就有两个相关的参数可以进行配置:
single-request-reopen
:发送 A 类型请求和 AAAA 类型请求使用不同的源端口,这样两个请求在 conntrack 表中不占用同一个表项,从而避免冲突。single-request
:避免并发,改为串行发送 A 类型和 AAAA 类型请求。没有了并发,从而也避免了冲突。
要给容器的 resolv.conf
加上 options 参数,有几个办法:
-
在容器的
ENTRYPOINT
或者CMD
脚本中,执行/bin/echo 'options single-request-reopen' >> /etc/resolv.conf
(不推荐) -
在 Pod 的 postStart hook 中添加:(不推荐)
lifecycle:postStart:exec:command:- /bin/sh- -c- "/bin/echo 'options single-request-reopen' >> /etc/resolv.conf
-
使用
template.spec.dnsConfig
配置:template:spec:dnsConfig:options:- name: single-request-reopen
-
使用 ConfigMap 覆盖 Pod 里面的
/etc/resolv.conf
:# configmap apiVersion: v1 data:resolv.conf: |nameserver 1.2.3.4search default.svc.cluster.local svc.cluster.local cluster.localoptions ndots:5 single-request-reopen timeout:1 kind: ConfigMap metadata:name: resolvconf --- # Pod Spec spec:volumeMounts:- name: resolv-confmountPath: /etc/resolv.confsubPath: resolv.conf # 在某个目录下面挂载一个文件(保证不覆盖当前目录)需要使用subPath -> 不支持热更新 ...volumes:- name: resolv-confconfigMap:name: resolvconfitems:- key: resolv.confpath: resolv.conf
-
使用 TCP:默认情况下 dns 的请求一般都是使用 UDP 请求的, 因为力求效率,不需要三握四挥。由于 TCP 没有这个问题,我们可以在容器的 resolv.conf 中增加
options use-vc
, 强制 glibc 使用 TCP 协议发送DNS query。template:spec:dnsConfig:options:- name: use-vc
-
使用
MutatingAdmissionWebhook
,用于对一个指定的资源的操作之前,对这个资源进行变更。我们也可以通过 MutatingAdmissionWebhook 来自动给所有 Pod 注入上面第三或第四种方法中的相关内容。
上面的方法在一定程度上可以解决 DNS 超时的问题,但更好的方式是使用本地 DNS 缓存,容器的 DNS 请求都发往本地的 DNS 缓存服务,也就不需要走 DNAT,当然也不会发生 conntrack
冲突了,而且还可以有效提升 CoreDNS 的性能瓶颈。
2、NodeLocal DNSCache
NodeLocal DNSCache
通过在集群节点上运行一个 DaemonSet 来提高集群 DNS 性能和可靠性。**处于 ClusterFirst 的 DNS 模式下的 Pod 可以连接到 kube-dns 的 serviceIP 进行 DNS 查询,**通过 kube-proxy 组件添加的 iptables 规则将其转换为 CoreDNS 端点。通过在每个集群节点上运行 DNS 缓存,NodeLocal DNSCache
可以缩短 DNS 查找的延迟时间、使 DNS 查找时间更加一致,以及减少发送到 kube-dns 的 DNS 查询次数。
在集群中运行 NodeLocal DNSCache
有如下几个好处:
- 如果本地没有 CoreDNS 实例,则具有最高 DNS QPS 的 Pod 可能必须到另一个节点进行解析,使用
NodeLocal DNSCache
后,拥有本地缓存将有助于改善延迟。 - 跳过 iptables DNAT 和连接跟踪将有助于减少 conntrack 竞争并避免 UDP DNS 条目填满 conntrack 表(上面提到的5s超时问题就是这个原因造成的)
注意:这里改成TCP的话,也是可以有效果的
- 从本地缓存代理到 kube-dns 服务的连接可以升级到 TCP,TCP conntrack 条目将在连接关闭时被删除,而 UDP 条目必须超时过后(默认
nfconntrackudp_timeout
是 30 秒) - 将 DNS 查询从 UDP 升级到 TCP 将减少归因于丢弃的 UDP 数据包和 DNS 超时的尾部等待时间,通常长达 30 秒(3 次重试+ 10 秒超时)
💘 实战:NodeLocal DNSCache-2023.2.21(测试成功)
- 实验环境
实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点k8s version:v1.20.0docker://20.10.7 #containerd都是一样的,次方法也使用k8s1.22/1.25
2021.12.28-实验软件-nodelocaldns
链接:https://pan.baidu.com/s/1cl474vfrXvz0hPya1EDIlQ
提取码:lpz1
nodelocaldns.yaml
1.获取NodeLocal DNSCache的资源清单
要安装 NodeLocal DNSCache
也非常简单,直接获取官方的资源清单即可:
wget https://github.com/kubernetes/kubernetes/raw/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml[root@master1 ~]#wget https://github.com/kubernetes/kubernetes/raw/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml
--2021-12-28 16:38:36-- https://github.com/kubernetes/kubernetes/raw/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml
Resolving github.com (github.com)... 20.205.243.166
Connecting to github.com (github.com)|20.205.243.166|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml [following]
--2021-12-28 16:38:36-- https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.111.133, 185.199.109.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 5334 (5.2K) [text/plain]
Saving to: ‘nodelocaldns.yaml’100%[===================================================================>] 5,334 --.-K/s in 0.1s2021-12-28 16:38:37 (51.4 KB/s) - ‘nodelocaldns.yaml’ saved [5334/5334][root@master1 ~]#ll nodelocaldns.yaml
-rw-r--r-- 1 root root 5334 Dec 28 16:38 nodelocaldns.yaml
[root@master1 ~]#
……
#该资源清单文件中我们重点看下 NodeLocalDNS 的配置对象:
---
apiVersion: v1
kind: ConfigMap
metadata:name: node-local-dnsnamespace: kube-systemlabels:addonmanager.kubernetes.io/mode: Reconcile
data:Corefile: |__PILLAR__DNS__DOMAIN__:53 {errorscache {success 9984 30denial 9984 5}reloadloopbind __PILLAR__LOCAL__DNS__ __PILLAR__DNS__SERVER__forward . __PILLAR__CLUSTER__DNS__ {force_tcp}prometheus :9253health __PILLAR__LOCAL__DNS__:8080}in-addr.arpa:53 {errorscache 30reloadloopbind __PILLAR__LOCAL__DNS__ __PILLAR__DNS__SERVER__forward . __PILLAR__CLUSTER__DNS__ {force_tcp}prometheus :9253}ip6.arpa:53 {errorscache 30reloadloopbind __PILLAR__LOCAL__DNS__ __PILLAR__DNS__SERVER__forward . __PILLAR__CLUSTER__DNS__ {force_tcp}prometheus :9253}.:53 {errorscache 30reloadloopbind __PILLAR__LOCAL__DNS__ __PILLAR__DNS__SERVER__forward . __PILLAR__UPSTREAM__SERVERS__prometheus :9253}
……
该资源清单文件中包含几个变量值得注意,其中:
__PILLAR__DNS__SERVER__
:表示 kube-dns 这个 Service 的 ClusterIP,可以通过命令kubectl get svc -n kube-system | grep kube-dns | awk'{ print $3 }'
获取(我们这里就是10.96.0.10
)__PILLAR__LOCAL__DNS__
:表示 DNSCache 本地监听的 IP 地址,该地址可以是任何地址,只要该地址不和你的集群里现有的 IP 地址发生冲突。 推荐使用本地范围内的地址,例如 IPv4 链路本地区段 169.254.0.0/16 内的地址(默认一般取 169.254.20.10 即可),或者 IPv6 唯一本地地址区段fd00::/8
内的地址__PILLAR__DNS__DOMAIN__
:表示集群域,默认就是cluster.local
另外还有两个参数 __PILLAR__CLUSTER__DNS__
和 __PILLAR__UPSTREAM__SERVERS__
,这两个参数会进行自动配置,对应的值来源于 kube-dns 的 ConfigMap 和定制的 Upstream Server
配置。
2.部署资源
- ⚠️ 这里需要注意的是镜像版本,本次使用
k8s-dns-node-cache:1.21.1
版本
直接执行如下所示的命令即可安装:
sed 's/k8s.gcr.io\/dns/cnych/g
s/__PILLAR__DNS__SERVER__/10.96.0.10/g
s/__PILLAR__LOCAL__DNS__/169.254.20.10/g
s/__PILLAR__DNS__DOMAIN__/cluster.local/g' nodelocaldns.yaml |
kubectl apply -f -#注意:这个使用的是老师的镜像中转地址cnych。
- 可以通过如下命令来查看对应的 Pod 是否已经启动成功:
[root@k8s-master1 ~]#kubectl get po -nkube-system -l k8s-app=node-local-dns -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
node-local-dns-bsl2n 1/1 Running 0 35h 172.29.9.32 k8s-node1 <none> <none>
node-local-dns-gnjnw 1/1 Running 0 35h 172.29.9.31 k8s-master1 <none> <none>
node-local-dns-z4cpj 1/1 Running 0 35h 172.29.9.33 k8s-node2 <none> <none>
3.测试
- 我们导出来一个pod看下情况:
[root@master1 ~]#kubectl get po node-local-dns-6mhj8 -nkube-system -oyaml
这里可以看到显示从169.254.20.10解析地址,如果没有再去找10.96.0.10的。
需要注意的是这里使用 DaemonSet 部署 node-local-dns 使用了 hostNetwork=true
,会占用宿主机的 8080 端口,所以需要保证该端口未被占用。
4.修改 kubelet 的 --cluster-dns
参数
先来确认下当前kube-proxy组件使用的模式是什么?
[root@master1 NodeLocalDnsCache]#kubectl get cm kube-proxy -nkube-system -oyaml|grep modemode: ipvs
但是到这里还没有完,如果 kube-proxy 组件使用的是 ipvs 模式的话,我们还需要修改 kubelet 的 --cluster-dns
参数,将其指向 169.254.20.10
,Daemonset 会在每个节点创建一个网卡来绑这个 IP,Pod 向本节点这个 IP 发 DNS 请求,缓存没有命中的时候才会再代理到上游集群 DNS 进行查询。
10: nodelocaldns: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group defaultlink/ether 6a:e9:a3:9b:03:a8 brd ff:ff:ff:ff:ff:ffinet 169.254.20.10/32 scope global nodelocaldnsvalid_lft forever preferred_lft foreverinet 10.96.0.10/32 scope global nodelocaldnsvalid_lft forever preferred_lft forever
[root@master1 ~]#
**iptables 模式下 Pod 还是向原来的集群 DNS 请求,节点上有这个 IP 监听,会被本机拦截,再请求集群上游 DNS,所以不需要更改 **--cluster-dns
参数。
- 由于我这里使用的是 kubeadm 安装的 1.20 版本的集群,所以我们只需要替换节点上
/var/lib/kubelet/config.yaml
文件中的 clusterDNS 这个参数值,然后重启即可:
sed -i 's/10.96.0.10/169.254.20.10/g' /var/lib/kubelet/config.yaml
systemctl daemon-reload && systemctl restart kubelet
注意:all节点均要配置。
5.验证
- 待 node-local-dns 安装配置完成后,我们可以部署一个新的 Pod 来验证下:
# test-node-local-dns.yaml
apiVersion: v1
kind: Pod
metadata:name: test-node-local-dns
spec:containers:- name: local-dnsimage: busybox:1.28.3command: ["/bin/sh", "-c", "sleep 60m"]
- 直接部署:
[root@master1 ~]#kubectl apply -f test-node-local-dns.yaml
pod/test-node-local-dns created
[root@master1 ~]#kubectl exec -it test-node-local-dns -- sh
/ # cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 169.254.20.10
options ndots:5
/ #
我们可以看到 nameserver 已经变成 169.254.20.10
了,当然对于之前的历史 Pod 要想使用 node-local-dns 则需要重建。
⚠️ 注意
如果担心线上环境修改
--cluster-dns
参数会产生影响,我们也可以直接在新部署的 Pod 中通过 dnsConfig 配置使用新的 localdns 的地址来进行解析。
- 创建yaml文件
#test-node-local-dns-2.yaml
apiVersion: v1
kind: Pod
metadata:name: test-node-local-dns-2
spec:dnsPolicy: None #None的时候需要配置下面的dnsConfigdnsConfig:nameservers: # 如果dnsPolicy不等于None,则会将nameservers合并到原有的(dnsPolicy默认是ClusterFirst)- 169.254.20.10searches:- default.svc.cluster.local- svc.cluster.local- cluster.localoptions:- name: ndotsvalue: "5"containers:- name: testimage: cnych/jessie-dnsutils:1.3command:- sleep- "infinity"imagePullPolicy: IfNotPresent
- 部署
[root@master1 ~]#kubectl apply -f test-node-local-dns-2.yaml
root@master1 ~]#kubectl exec -it test-node-local-dns-2 -- bash
# cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 169.254.20.10
options ndots:5
#
- 我们可以看到 nameserver 已经变成 169.254.20.10 了,同样简单测试下是否可以正常工作:
[root@k8s-master1 ~]#kubectl exec -it test-node-local-dns-2 -- bash
root@test-node-local-dns-2:/# cat /etc/resolv.conf
nameserver 169.254.20.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
root@test-node-local-dns-2:/# nslookup youdianzhishi.com
Server: 169.254.20.10
Address: 169.254.20.10#53Non-authoritative answer:
Name: youdianzhishi.com
Address: 39.106.22.102root@test-node-local-dns-2:/# nslookup kubernetes.default
Server: 169.254.20.10
Address: 169.254.20.10#53Name: kubernetes.default.svc.cluster.local
Address: 10.96.0.1root@test-node-local-dns-2:/#
⚠️ 说明:以下步骤是之前实验测试保留的数据。
6.重建前面压力测试 DNS 的 Pod
接下来我们重建前面压力测试 DNS 的 Pod,重新将 testdns 二进制文件拷贝到 Pod 中去:
[root@master1 ~]#kubectl delete -f nginx.yaml
deployment.apps "nginx" deleted
[root@master1 ~]#kubectl apply -f nginx.yaml
deployment.apps/nginx created
[root@master1 ~]#kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-5d59d67564-kgd4q 1/1 Running 0 22s
nginx-5d59d67564-lxnt2 1/1 Running 0 22s
test-node-local-dns 1/1 Running 0 5m50s[root@master1 ~]#kubectl cp go/testdns nginx-5d59d67564-kgd4q:/root
[root@master1 ~]#kubectl exec -it nginx-5d59d67564-kgd4q -- bash
root@nginx-5d59d67564-kgd4q:/# cd /root/
root@nginx-5d59d67564-kgd4q:~# ls
testdns
root@nginx-5d59d67564-kgd4q:~# cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 169.254.20.10
options ndots:5
root@nginx-5d59d67564-kgd4q:~##自己本次的测试数据
#再次压测
#先来个200个并发,测试三次
root@nginx-5d59d67564-kgd4q:~# ./testdns -host nginx-service.default -c 200 -d 30 -l 5000
request count:47344
error count:0
request time:min(1ms) max(976ms) avg(125ms) timeout(0n)
root@nginx-5d59d67564-kgd4q:~# ./testdns -host nginx-service.default -c 200 -d 30 -l 5000
request count:49744
error count:0
request time:min(1ms) max(540ms) avg(118ms) timeout(0n)
root@nginx-5d59d67564-kgd4q:~# ./testdns -host nginx-service.default -c 200 -d 30 -l 5000
request count:55929
error count:0
request time:min(2ms) max(463ms) avg(105ms) timeout(0n)
root@nginx-5d59d67564-kgd4q:~#
root@nginx-5d59d67564-kgd4q:~##再来个1000个并发,测试三次
root@nginx-5d59d67564-kgd4q:~# ./testdns -host nginx-service.default -c 1000 -d 30 -l 5000
request count:42177
error count:0
request time:min(16ms) max(2627ms) avg(690ms) timeout(0n)
root@nginx-5d59d67564-kgd4q:~# ./testdns -host nginx-service.default -c 1000 -d 30 -l 5000
request count:45456
error count:0
request time:min(29ms) max(2484ms) avg(650ms) timeout(0n)
root@nginx-5d59d67564-kgd4q:~# ./testdns -host nginx-service.default -c 1000 -d 30 -l 5000
request count:45713
error count:0
request time:min(3ms) max(1698ms) avg(647ms) timeout(0n)
root@nginx-5d59d67564-kgd4q:~#
#注意:这个1000并发测试效果就很明显了
老师笔记的测试数据:
# 拷贝到重建的 Pod 中
$ kubectl cp testdns svc-demo-546b7bcdcf-b5mkt:/root
$ kubectl exec -it svc-demo-546b7bcdcf-b5mkt -- /bin/bash
root@svc-demo-546b7bcdcf-b5mkt:/# cat /etc/resolv.conf
nameserver 169.254.20.10 # 可以看到 nameserver 已经更改
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
root@svc-demo-546b7bcdcf-b5mkt:/# cd /root
root@svc-demo-546b7bcdcf-b5mkt:~# ls
testdns
# 重新执行压力测试
root@svc-demo-546b7bcdcf-b5mkt:~# ./testdns -host nginx-service.default -c 200 -d 30 -l 5000
request count:16297
error count:0
request time:min(2ms) max(5270ms) avg(357ms) timeout(8n)
root@svc-demo-546b7bcdcf-b5mkt:~# ./testdns -host nginx-service.default -c 200 -d 30 -l 5000
request count:15982
error count:0
request time:min(2ms) max(5360ms) avg(373ms) timeout(54n)
root@svc-demo-546b7bcdcf-b5mkt:~# ./testdns -host nginx-service.default -c 200 -d 30 -l 5000
request count:25631
error count:0
request time:min(3ms) max(958ms) avg(232ms) timeout(0n)
root@svc-demo-546b7bcdcf-b5mkt:~# ./testdns -host nginx-service.default -c 200 -d 30 -l 5000
request count:23388
error count:0
request time:min(6ms) max(1130ms) avg(253ms) timeout(0n)
7.总结
从上面的结果可以看到无论是最大解析时间还是平均解析时间都比之前默认的 CoreDNS 提示了不少的效率,NodeLocal DNSCache 可以提升 DNS 的性能和可靠性的,所以也非常推荐用在生产环境,唯一的缺点就是由于LocalDNS 使用的是 DaemonSet 模式部署,所以如果需要更新镜像则可能会中断服务(不过可以使用一些第三方的增强组件来实现原地升级解决这个问题,比如 openkruise)。
阿里云也是比较推荐线上去部署这个的。
测试结束。😘
关于我
我的博客主旨:
- 排版美观,语言精炼;
- 文档即手册,步骤明细,拒绝埋坑,提供源码;
- 本人实战文档都是亲测成功的,各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人帮您解决问题,让我们一起进步!
🍀 微信二维码
x2675263825 (舍得), qq:2675263825。
🍀 微信公众号
《云原生架构师实战》
🍀 csdn
https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421
🍀 知乎
https://www.zhihu.com/people/foryouone
最后
好了,关于本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!
相关文章:

LocalDNS
目录 文章目录目录本节实战DNS优化1、dns 5s 超时问题解决办法2、NodeLocal DNSCache实验软件关于我最后本节实战 实战名称💘 实战:NodeLocal DNSCache-2022.7.30(测试成功)💘 实战:NodeLocal DNSCache-2023.2.21(测试成功) DNS优…...

线程池种类和拒绝策略
1、newCachedThreadPool():可缓存的线程池,核心线程数量为0,最大线程数量为INT_MAX。线程空闲时间超过60秒被回收。适合处理大量小任务。 2、newFixedThreadPool()。固定线程个数的线程池,线程都是核心线程,没有应急线…...

Python制作9行最简单音乐播放器?不,我不满足
嗨害大家好鸭~我是小熊猫 好久不见啦~这次就来给大家整个大福利 ~ 源码资料电子书:点击此处跳转文末名片获取 最简单的9行代码音乐播放器如下: import time import pygamefile r歌曲路径 pygame.mixer.init() print(正在播放,file) track pygame.mixer.music.lo…...

零基础小白如何学会数据分析?
随着数字经济、大数据时代的发展,数据已然成为当下时代最重要的盈利资源,让企业在做决策和计划方案时更有针对性和依据,能提前预测市场发展方向,做好布局。由此而产生的数据分析岗位也逐渐被更多企业重视,特别是中大型…...

【Linux】vim的使用及常用快捷键(不会使用vim?有这篇文章就够了)
🔥🔥 欢迎来到小林的博客!! 🛰️博客主页:✈️小林爱敲代码 🛰️欢迎关注:👍点赞🙌收藏✍️留言 目录💖vim的基本概念vi…...

刷完这19道leetcode二分查找算法,不信进不了大厂
对于二分题,其实就是设定一个中间值 mid, 然后通过这个值进行一个判断 check(mid), 通过这个函数的返回值,判断将不可能的一半剪切掉; 在刷题的时候需要注意主要是两部分,check 函数的定义以及边界的选择(…...

四、Plugin Request and Sometimes pads
Request and Sometimes pads 到目前为止,我们只处理了总是可用的pad。然而,也有一些pad仅在某些情况下创建,或者仅在应用程序请求pad时创建。第一个有时被称为a;第二个被称为请求pad。pad的可用性(always, sometimes or request)可以在pad的…...

唤醒手腕 Java 后端 Springboot 结合 Redis 数据库学习笔记(更新中)
Redis 基本介绍 Redis Introduction The open source, in-memory data store used by millions of developers as a database, cache, streaming engine, and message broker. 基本概念:redis 是一个开源的、使用 C 语言编写的、支持网络交互的、可基于内存也可持…...

robotiq 2f 140安装在UR3机械臂后面在gazebo仿真中散架、抖动
robotiq 2f 140安装在UR3机械臂后面在gazebo仿真中散架、抖动 搭建环境: ubuntu: 20.04 ros: Nonetic sensor: robotiq_ft300 gripper: robotiq_2f_140_gripper UR: UR3 通过上一篇博客配置好ur3、力传感器和robotiq夹爪的gazebo仿真环境后,夹爪看起来…...

坐标系概念 四元数 欧拉角
1、四个概念:“地理”坐标系、“机体”坐标系、他们之间换算公式、换算公式用的系数。地理坐标系:东、北、天,以下简称地理。在这个坐标系里有重力永远是(0,0,1g),地磁永远是(0,1,x)…...

从0开始写Vue项目-SpringBoot整合Mybatis-plus实现登录、注册功能
1.从0开始写Vue项目-环境和项目搭建_慕言要努力的博客-CSDN博客 2. 从0开始写Vue项目-Vue2集成Element-ui和后台主体框架搭建_慕言要努力的博客-CSDN博客 3. 从0开始写Vue项目-Vue页面主体布局和登录、注册页面_慕言要努力的博客-CSDN博客 一、前言 在之前我们以及搭建好了基…...

K8s中gRpc通信负载均衡失效
上篇文章在做 整合K8sSpringCloudK8sSpringBootgRpc 时,发现K8s中使用gRpc通信,负载均衡功能失效查了下gRpc的最佳实践,找到这里Load balancingSome load balancers dont work effectively with gRPC. L4 (transport) load balancers operate…...

第三届区块链服务网络(BSN)全球合作伙伴大会在杭州成功举办
为持续推动分布式技术和产业创新发展,2023年2月17日,由杭州市人民政府指导,杭州市拱墅区人民政府、国家信息中心主办,中国移动通信集团有限公司、区块链服务网络(BSN)发展联盟承办,中国移动通信…...

人工智能基础部分13-LSTM网络:预测上证指数走势
大家好,我是微学AI,今天给大家介绍一下LSTM网络,主要运用于解决序列问题。 一、LSTM网络简单介绍 LSTM又称为:长短期记忆网络,它是一种特殊的 RNN。LSTM网络主要是为了解决长序列训练过程中的梯度消失和梯度爆炸问题…...

内网穿透/组网/设备上云平台EasyNTS上云网关的安装操作指南
EasyNTS上云网关的主要作用是解决异地视频共享/组网/上云的需求,网页对域名进行添加映射时,添加成功后会生成一个外网访问地址,在浏览器中输入外网访问地址,即可查看内网应用。无需开放端口,EasyNTS上云网关平台会向Ea…...

易点天下基于 StarRocks 全面构建实时离线一体的湖仓方案
作者:易点天下数据平台团队易点天下是一家技术驱动发展的企业国际化智能营销服务公司,致力于为客户提供全球营销推广服务,通过效果营销、品牌塑造、垂直行业解决方案等一体化服务,帮助企业在全球范围内高效地获取用户、提升品牌知…...

Tomcat的类加载机制
不遵循双亲委托 在JVM中并不是一次性地把所有的文件都加载到,而是按需加载,加载机制采用 双亲委托原则,如下图所示: BootStrapClassLoader 引导类加载器ExtClassLoader 扩展类加载器AppClassLoader 应用类加载器CustomClassLoad…...

【shell 编程大全】数组,逻辑判断以及循环
数组,逻辑判断以及循环1. 概述 大家好,我又来了。今天呢我们继续学习shell相关的知识。还是老样子我们先回顾下上一次【脚本交互 以及表达式】学习到的知识 登录shell 关联配置文件什么是子shellumask 修改默认权限read 基础表达式 简单计算表达式expr 计…...

Android13 Bluetooth更新
目录 Android 13 版本说明 LE Audio 代码更新 Android 12代码路径 Android 13代码路径 Android 13 版本说明 里面对蓝牙更新的描述较少,一出提到蓝牙的一...

手工测试混了5年,年底接到了被裁员的消息....
大家都比较看好软件测试行业,只是因为表面上看起来:钱多事少加班少。其实这个都是针对个人运气好的童人才会有此待遇。在不同的阶段做好不同阶段的事情,才有可能离这个目标更近,作为一枚软件测试人员,也许下面才是我们…...

Umi框架
什么是 umi umi 是由 dva 的开发者 云谦 编写的一个新的 React 开发框架。umi 既是一个框架也是一个工具,可以将它简单的理解为一个专注性能的类 next.js 前端框架,并通过约定、自动生成和解析代码等方式来辅助开发,减少开发者的代码量。 u…...

教你学git
前言 git是一种用于多人合作写项目。详细说明如下 文章目录前言什么是版本控制?什么是 Git?它就属于人工版本控制器版本控制工具常见版本控制工具怎么工作的?git 文件生命周期状态区域安装配置-- global检查配置创建仓库工作流与基本操作查看…...

【工作笔记】syslog,kern.log大量写入invalid cookie错误信息问题
任务描述 错误出现出现过四五次,应该是诊断单元tf卡读写出问题导致下面这条告警一直高频写入到/var/log/下的syslog、kern.log、messages中 Nov 23 06:25:12 embest kernel: omap_hsmmc 48060000.mmc: [omap_hsmmc_pre_dma_transfer] invalid cookie: data->hos…...

【C++】多线程
多任务处理有两种形式,即:多进程和多线程。 基于进程的多任务处理是程序的并发执行。基于线程的多任务处理是同一程序的片段的并发执行 文章目录1. 多线程介绍2. Windows多线程1. 多线程介绍 每一个进程(可执行程序)都有一个主线…...

0202插入删除-算法第四版红黑树-红黑树-数据结构和算法(Java)
文章目录4 插入4.1 序4.2 向单个2-结点插入新键4.3 向树底部的2-结点插入新键4.4 向一棵双键树(3-结点)中插入新键4.5 颜色调整4.6 根结点总是黑色4.7 向树底部的3-结点插入新键4.8 将红链接在树中向上传递4.9 实现5 删除5.1 删除最小键5.2 删除6 有序性…...

vue 生成二维码插件 vue-qr使用方法
一、安装 npm install vue-qr --save二、引入 import VueQr from vue-qrcomponents:{VueQr,},三、使用 <vue-qr:text"dyQrcode":size"170":logoSrc"logo":margin"6":logoScale"0.2"></vue-qr>四、属性说明 …...

网络工程课(二)
ensp配置vlan 一、配置计算机ip地址和子网掩码 二、配置交换机LSW1 system-view [Huawei]sysname SW1 [SW1]vlan batch 10 20 [SW1]interface Ethernet0/0/1 [SW1-Ethernet0/0/1]port link-type access 将接口设为access接口 [SW1-Ethernet0/0/1]port default vlan 10 [SW1-E…...

Pytorch并行计算(三): 梯度累加
梯度累加 梯度累加(Gradient Accmulation)是一种增大训练时batch size的技巧。当batch size在一张卡放不下时,可以将很大的batch size分解为一个个小的mini batch,分别计算每一个mini batch的梯度,然后将其累加起来优…...

蓝桥杯入门即劝退(十八)最小覆盖子串(滑动窗口解法)
欢迎关注点赞评论,共同学习,共同进步! ------持续更新蓝桥杯入门系列算法实例-------- 如果你也喜欢Java和算法,欢迎订阅专栏共同学习交流! 你的点赞、关注、评论、是我创作的动力! -------希望我的文章…...

Android一~
进程和线程的区别https://zhuanlan.zhihu.com/p/60375108https://zhuanlan.zhihu.com/p/138689342线程池的用法和原理tcp三次握手和四次挥手、tcp基础http请求报文格式二叉树中序遍历(算法)activity启动模式OKhttp源码讲解Java修饰符Java线程同步的方法s…...