- 创建者: 虚拟的现实,上次更新时间:9月 06, 2024 需要 3 分钟阅读时间
应用层场景
dns
Linux 上 DNS 相关配置就是 /etc/resolv.conf 文件里的 nameserver ,而里面所有可配置项目见 man 手册页 ,常见的就是下面的选项:
- nameserver,不要配置超过 3 个,见文章 CentOS中resolv.conf的配置实验
- search
- nodot
- 和一些常见的 options
nslookup
nslookup 分为交互和非交互模式,不带任何选项和参数执行就是交互模式,交互模式能力稍微强点:
$ nslookup www.baidu.com Server: 127.0.0.53 Address: 127.0.0.53#53 Non-authoritative answer: www.baidu.com canonical name = www.a.shifen.com. Name: www.a.shifen.com Address: 183.2.172.42 Name: www.a.shifen.com Address: 183.2.172.185
此处 DNS server IP 是 127.0.0.53 是因为有些 Linux 发行版会使用 systemd-resolved 在本机起一个 DNS server,通过命令来配置上游 DNS :
$ cat /etc/resolv.conf nameserver 127.0.0.53 options edns0 trust-ad # 使用 resolvectl 命令查看 $ resolvectl -h $ resolvectl --no-pager status $ resolvectl --no-pager statistics
在一些 initContainer 里有些人喜欢做一些前置依赖检查 service 域名解析可用性,而早期 K8S 官方文档里推荐使用 busybox:1.28 里的 nslookup,后续有不少人发现升级 busybox 后无法解析了:
# busybox:1.28 $ nslookup kubernetes.default Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: kubernetes.default Address 1: 10.96.0.1 kubernetes.default.svc.cluster.local # busybox:1.31.1 $ nslookup kubernetes.default Server: 10.96.0.10 Address: 10.96.0.10:53 ** server can't find kubernetes.default: NXDOMAIN *** Can't find kubernetes.default: No answer command terminated with exit code 1
这个问题是见 issue docker-library/busybox#48,所以一般 DNS 排查过程中不推荐使用 nslookup 命令,但是只是简单解析的话,可以找个 glibc 镜像,使用以下黑科技:
# https://github.com/bitnami/containers/blob/main/bitnami/git/2/debian-12/prebuildfs/opt/bitnami/scripts/libnet.sh#L26 $ getent ahostsv4 kubernetes.default | awk '/STREAM/ {print $1;exit; }' 10.96.0.1 $ getent ahostsv4 kube-dns.kube-system | awk '/STREAM/ {print $1;exit; }' 10.96.0.10
dig
排查 DNS 问题建议使用更强大的 dig @server name type 命令,很多程序的 DNS 解析行为都是用的 glibc 提供的库,而避免因素干扰,dig 可以完全从命令行来指定 DNS 的解析逻辑:
# 使用默认的 DNS 解析 $ dig www.baidu.com ; <<>> DiG 9.16.48-Ubuntu <<>> www.baidu.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21504 ;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 65494 ;; QUESTION SECTION: ;www.baidu.com. IN A ;; ANSWER SECTION: www.baidu.com. 60 IN CNAME www.a.shifen.com. www.a.shifen.com. 59 IN A 183.2.172.42 www.a.shifen.com. 59 IN A 183.2.172.185 ;; Query time: 0 msec ;; SERVER: 127.0.0.53#53(127.0.0.53) ;; WHEN: Mon Jul 15 14:53:38 CST 2024 ;; MSG SIZE rcvd: 101 # 简洁输出,缺省是查询 A 记录 $ dig +short baidu.com 39.156.66.10 110.242.68.66 # tcp dns 解析 $ dig +short +tcp baidu.com # 使用指定 DNS 解析 $ dig @223.5.5.5 +short baidu.com # 使用指定端口解析 $ dig @223.5.5.5 -p 53 baidu.com # Pod 容器内使用 resolv.conf 里的 search 查找,因为默认行为是 +nosearch 的 $ dig +short kubernetes.default +search
例如宿主机上有 dig 命令,测试 coredns 能否解析:
$ dig @10.96.0.10 +short kubernetes.default.svc.cluster.local # 或者绕过 svc,使用指定 coredns POD_IP 还不通就是 CNI 或者跨节点的问题 $ dig @<POD_IP> +short kubernetes.default.svc.cluster.local
curl
当然,在面对更复杂的 http 接口排错时候,更多还是使用 curl 命令发送或者模拟 http 请求,curl 命令不单单是支持 http 协议,还支持其他协议,这里暂不讨论:
$ curl -V curl 7.68.0 (x86_64-pc-linux-gnu) libcurl/7.68.0 OpenSSL/1.1.1f zlib/1.2.11 brotli/1.0.7 libidn2/2.2.0 libpsl/0.21.0 (+libidn2/2.2.0) libssh/0.9.3/openssl/zlib nghttp2/1.40.0 librtmp/2.3 Release-Date: 2020-01-08 Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp # ↑ 这里是协议支持 Features: AsynchDNS brotli GSS-API HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets
只看返回的头部,也就是 HEAD 请求
-v 选项打印详细信息,包含域名解析到的 IP,https 证书,发起的头部信息,然后接口 http://httpbin.org/get 会返回客户端的 header 信息
$ curl -I http://httpbin.org $ curl -v http://httpbin.org/get * Trying 35.173.225.247:80... * TCP_NODELAY set * Connected to httpbin.org (35.173.225.247) port 80 (#0) > GET /get HTTP/1.1 > Host: httpbin.org > User-Agent: curl/7.68.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Date: Mon, 15 Jul 2024 08:05:33 GMT < Content-Type: application/json < Content-Length: 254 < Connection: keep-alive < Server: gunicorn/19.9.0 < Access-Control-Allow-Origin: * < Access-Control-Allow-Credentials: true < { "args": {}, "headers": { "Accept": "*/*", "Host": "httpbin.org", "User-Agent": "curl/7.68.0", "X-Amzn-Trace-Id": "Root=1-6694d84d-29cfb5b87bcaeb267f3b918f" }, "origin": "178.xx.xx.xx", "url": "http://httpbin.org/get" }
-H key: value 设置 header
$ curl http://httpbin.org/get -H 'test: 11111111111111' { "args": {}, "headers": { "Accept": "*/*", "Host": "httpbin.org", "Test": "11111111111111", "User-Agent": "curl/7.68.0", "X-Amzn-Trace-Id": "Root=1-6694d921-0449f11d77d437e71b7113fc" }, "origin": "178.236.xx.xx", "url": "http://httpbin.org/get" }
-X method ,例如发送 post 请求
$ curl -XPOST http://httpbin.org/post?a=123 --data-raw '{"key":"value"}' { "args": { "a": "123" }, "data": "", "files": {}, "form": { "{\"key\":\"value\"}": "" }, "headers": { "Accept": "*/*", "Content-Length": "15", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "curl/7.68.0", "X-Amzn-Trace-Id": "Root=1-6694d982-180db3df277a1ce879676d16" }, "json": null, "origin": "178.236.xx.xx", "url": "http://httpbin.org/post?a=123" }
一些其他常见选项:
- -o file 把 body 内容存到文件,下载文件时候使用
- -k, --insecure 允许非安全连接,通常 https 由非权威 ca 签署证书,例如 kubernetes 的接口,curl -k https://10.96.0.1
- -L --location 跟随重定向
而对于浏览器触发的请求,我们也可以 F12 network 里拷贝成 curl 命令格式,如下图:
然后更改一些参数 curl 发请求,调试后端逻辑之类的。需要注意的是,有些后端逻辑会有防重放防御,也就是一个 http 请求发送后,再发送就无效了。
--resolve 选项方便你来不修改 hosts 来指定域名的 IP :
# curl --resolve <host:port:address> <URL> $ curl --resolve example.com:80:127.0.0.1 http://example.com
一个要注意点的是,有时候后端逻辑会根据 User-Agent 做判断,浏览器看到的是 html 页面,curl 或者一些编程语言的 http 库请求后是 json 接口信息,当然不单单是 UA 字段。
还有有些网站避免爬虫,会利用浏览器的一些功能做人机校验,curl 是做不到那些的。
负载均衡
软硬件实现手段为:
- 云上 SLB 之类的
- 硬件 LB
- 软件负载均衡,nginx、haproxy、keepalived + haproxy、Envoy....
- 内核能力 lvs 之类的
- 以及网络设备配置 ospf 和服务器 lvs 结合 ...
- 无标签
0 评论