CheatSheet_Kubernetes
移除所有失败的podkubectl delete pod --field-selector="status.phase==Failed"
查看证书信息查看 AWS LoadBalancer 证书的信息,检查证书的有效期:
kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io aws-load-balancer-webhook -ojsonpath={.webhooks[0].clientConfig.caBundle} | base64 -d | openssl x509 -noout -text
使用 Debug 容器# 给特定的容器附加一个Sidecar, 并启动shell。
kubectl debug -it --image=public.ecr.aws/amazonlinux/amazonlinux:latest aws-node-cpmck
# netshoot容器, 比较方便的用来进行网络部分的调试。
# 项目仓库地址: https://github.com/nicolaka/netshoot
kubectl debug mypod -it --image=nicolaka/netshoot
查看EKS集群插件的兼容范围aws eks describe-addon-versions --kubernetes-version 1.25 --addon-name vpc-cni | grep addonVersion
列出节点上所有容器的镜像名称# ssh 到节点上面执行
nerdctl inspect $(nerdctl ps -a -q) | grep -i "image.:" | sort -f
# 清理节点上未使用的镜像,不仅仅是 dangling image
nerdctl image prune -af
# 设置 nerdctl 命令的自动补全
nerdctl completion bash > /etc/bash_completion.d/nerdctl
CheatSheet_Linux
PS 查看 Cpu, Mem 最高几个进程# Top CPU users
ps auxwww --sort -%cpu | head -20
# Top memory users
ps auxwww --sort -rss | head -20
ps auxf --width=200
or
ps auxwwwf
Curl 显示详细的http连接时间curl -o /dev/null -s -w "time_namelookup:%{time_namelookup}\ntime_connect: %{time_connect}\ntime_appconnect: %{time_appconnect}\ntime_redirect: %{time_redirect}\ntime_pretransfer: %{time_pretransfer}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n" http://nginx.liarlee.site/Fedora-Workstation-Live-x86_64-38_Beta-1.3.iso
Sysctl 查看 Tcp 相关的内核参数sysctl -a | egrep "rmem|wmem|tcp_mem|adv_win|moderate|slow_start"
查看系统内所有用户的Crontab~]$ cat /etc/passwd | cut -f 1 -d : | xargs -I {} crontab -l -u {}
no crontab for root
no crontab for bin
no crontab for daemon
no crontab for adm
no crontab for lp
no crontab for sync
no crontab for shutdown
no crontab for halt
no crontab for mail
no crontab for operator
no crontab for games
no crontab for ftp
no crontab for nobody
no crontab for systemd-network
no crontab for dbus
no crontab for rpc
no crontab for libstoragemgmt
no crontab for sshd
no crontab for rpcuser
no crontab for nfsnobody
no crontab for rngd
no crontab for ec2-instance-connect
no crontab for postfix
no crontab for chrony
no crontab for tcpdump
no crontab for ec2-user
no crontab for tss
no crontab for netdata
no crontab for cwagent
no crontab for ssm-user
查看AWS EC2 的 Billing Code对于EC2来说,Redhat 或者 SUSE 的 Enterprise版本是有Billing Code的, 这标记了是否是已经付费过的版本, 有没有安全补丁和技术支持。
# IDMSv1可以使用如下命令:
curl http://169.254.169.254/latest/dynamic/instance-identity/document
# IDMSv2可以使用:
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` && curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/dynamic/instance-identity/document
查看SUSE的注册情况,以及是否启用 LTSSsudo SUSEConnect --list-extensions
Linux 查看网络可能存在的丢包和异常。> ip -s link show wlan0
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc cake state UP mode DORMANT group default qlen 1000
link/ether dc:a6:32:a2:77:a1 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped missed mcast
1479773800 3264136 0 0 0 29898
TX: bytes packets errors dropped carrier collsns
2132719784 3716055 0 0 0 0
> ethtool -S end0 | grep drop
rx_dropped: 0
tx_dropped: 0
rxq0_dropped: 0
rxq1_dropped: 0
rxq2_dropped: 0
rxq3_dropped: 0
rxq16_dropped: 0
Openssl 建立连接测试openssl s_client -debug --connect some.domain.com:443
# 指定算法和协议版本
openssl s_client -debug --connect some.domain.com:443 -tls1_2 -cipher RC4
查看系统内的日志, 不同级别# 查看启动以来的内核日志
journalctl -xeak
# 查看error级别的日志( 这个日志级别不是所有的应用程序都按照规则设定, 有的程序都是info级别, 没有做区分。
journalctl -xeak -p3
# 日志级别的补充说明:
# FROM..TO. The log levels are the usual syslog log levels as documented in syslog(3), i.e. "emerg" (0), "alert" (1), "crit" (2), "err" (3), "warning" (4), "notice" (5), "info" (6), "debug" (7). If a
# single log level is specified, all messages with this log level or a lower (hence more important) log level are shown. If a range is specified, all messages within the range are shown, including both
# the start and the end value of the range. This will add "PRIORITY=" matches for the specified priorities.
# 输出所有重启的历史记录
# 命令会通过序号的方式标记重启的记录, 0, -1, -2, -3 等等
journalctl --list-boots
0 cfa4ea7ba29d44879e21e0406455bd50 Wed 2024-01-31 17:41:24 UTC—Thu 2024-02-01 05:58:11 UTC
# 输出上次系统启动的日志
journalctl -xeab -1
# 输出到console不是pager进行分页, 可以接 grep
journalctl -xea --no-pager
# 输出kubelet这个 service 日志
journalctl -xeau kubelet
# 追踪这个服务的日志, 相当于 tail -f
journalctl -xeafu kubelet
# 显示100行
journalctl -xeau kubelet -n 100 --no-pager
# 显示从什么时间开始的日志 或者 到什么时间为止的日志。
# Format: 2012-10-30 18:17:16
# 可以仅仅提供日期字段, 时间会默认全0
-S, --since=, -U, --until=
journalctl -xea --no-pager -S "2024-01-31 18:20:00" -U "2024-01-31 18:40:00"
# 更多:
journalctl -xea -u kubelet --no-pager -S "2024-01-31 17:40:00" -U "2024-01-31 23:40:00"
Tshark 命令简单说明tshark -i ens5 -n -f 'tcp dst port 32123' -T fields -e frame.number -e frame.time_epoch -e frame.time_delta_displayed -e ip.src -e tcp.srcport -e ip.dst -e tcp.dstport -e tcp.time_delta -e tcp.stream -e tcp.len -e tcp.analysis.ack_rtt
# 抓取 dns 请求, 并显示 IP TTL 以及 DNS TTL, 格式化输出
> sudo tshark -i ens5 -Y 'dns' -T fields -e ip.src -e ip.dst -e dns.qry.name -e ip.ttl -E header=y -E separator='/t' -E quote='d' -E occurrence=f
Iptables 常用命令关于 iptables 的扩展内容: [[Linux/Linux_Iptables-and-conntrack|Linux_Iptables-and-conntrack]]
清理Kubernetes所有的路由条目(流量会中断iptables -X && iptables -F && iptables -Z && iptables -t nat -F && iptables -t nat -X && iptables -t nat -Z
查看 Iptables 中的规则,并标记显示行号# 查看 nat 表
iptables -t nat -nvL --line-number
# 爱看 filter 表
iptables -nvL --line-number
# 查看 raw 表
iptables -t raw -nvL --line-number
增加、 ...
CheatSheet_awscli
查看实例和对应实例的系统平台信息aws ec2 describe-instances --query "Reservations[*].Instances[*].{InstanceId:InstanceId,PlatformDetails:Platform}" --output table
查看实例和EBS的关联关系aws ec2 describe-volumes --query 'Volumes[*].[VolumeId, Attachments[0].InstanceId, Size]' --output table
AWS-CNI 集成 Calico 并启用 WireGuard 加密
看了下说明, 这个东西的主要作用是用于节点间Pod流量的加密。
启动集群略
Helm命令安装 Calico
添加一个helm repohelm repo add projectcalico https://docs.tigera.io/calico/charts
创建一个 value.yamlcat > values.yaml <<EOF
installation:
kubernetesProvider: EKS
registry: reg.liarlee.site/docker.io
EOF
helm show values projectcalico/tigera-operator --version v3.27.2
通过命令安装kubectl create namespace tigera-operator
helm install calico projectcalico/tigera-operator --version v3.27.2 -f values.yaml --namespace tigera-operator
watch kubectl get pods -n calico-system
启用 WireGuardkubectl patch felixconfiguration default --type='merge' -p '{"spec":{"wireguardEnabled":true}}'
# 在节点上面可以看到 wireguard 的网卡 和 内核模块, 说明已经成功了。
# EKS 默认的 AMI 里面是带这个模块的, 不需要手动安装, 可以自动按需装载。
~]$ lsmod | grep wireguard
wireguard 98304 0
curve25519_x86_64 36864 1 wireguard
libcurve25519_generic 49152 2 curve25519_x86_64,wireguard
libchacha20poly1305 16384 1 wireguard
ip6_udp_tunnel 16384 1 wireguard
udp_tunnel 28672 1 wireguard
~]$ ip ad
35: wireguard.cali: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 8941 qdisc noqueue state UNKNOWN group default qlen 1000
link/none
inet 192.168.137.134/32 scope global wireguard.cali
valid_lft forever preferred_lft forever
# 或者可以查看
> kubectl get felixconfiguration default -o yaml
apiVersion: projectcalico.org/v3
kind: FelixConfiguration
...
spec:
bpfConnectTimeLoadBalancing: TCP
bpfHostNetworkedNATWithoutCTLB: Enabled
bpfLogLevel: ""
floatingIPs: Disabled
healthPort: 9099
logSeverityScreen: Info
reportingInterval: 0s
routeTableRange:
max: 99
min: 65
vxlanVNI: 4096
wireguardEnabled: true
参考文档Project Calico:https://docs.tigera.io/calico/3.25/network-policy/encrypt-cluster-pod-traffic#enable-wireguard-for-a-cluster
使用 nsenter 从Kubernetes Node 进入容器网络 Namespace
记录一下使用 nsenter 进入容器的 network namespace 中抓包。在 TroubleShooting 的过程中可能是需要这个方法的。
进入容器ns的步骤
选中一个poddefault haydenarch-68865d5b56-cblc6 ● 1/1 Running 0 172.31.48.162 ip-172-31-53-61.cn-north-1.compute.internal
在节点上找到这个pod的容器id : 02182f3e9137[root@ip-172-31-53-61 ~]$ nerdctl ps| grep archlinux
02182f3e9137 1234567.dkr.ecr.cn-north-1.amazonaws.com.cn/archlinux:latest "sleep infinity" 23 hours ago Up k8s://default/arch-68865d5b56-cblc6/arch
查找这个容器id的进程pid。[root@ip-172-31-53-61 ~]$ nerdctl inspect 02182f3e9137 | grep -i pid
"Pid": 10306,
nsenter 命令进入容器的名称空间。 [root@ip-172-31-53-61 ~]$ nsenter -t 10306 -n
[root@ip-172-31-53-61 ~]$ ip ad
3: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
link/ether 22:fb:14:7b:91:22 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.31.48.162/32 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::20fb:14ff:fe7b:9122/64 scope link
valid_lft forever preferred_lft forever
对比容器里面执行命令的结果: [root@haydenarch-68865d5b56-cblc6 /]$ ip ad
3: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
link/ether 22:fb:14:7b:91:22 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.31.48.162/32 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::20fb:14ff:fe7b:9122/64 scope link
valid_lft forever preferred_lft forever
这时候就可以使用节点上面的工具来进行抓包了。
测试可以看到在容器内部是没有tcpdump命令的.
[root@haydenarch-68865d5b56-cblc6 /]$ tcpdump
bash: tcpdump: command not found
在容器内发出一个ping包 。
[root@haydenarch-68865d5b56-cblc6 /]$ ping www.bing.com -c 1
PING a-0001.a-msedge.net (13.107.21.200) 56(84) bytes of data.
64 bytes from 13.107.21.200 (13.107.21.200): icmp_seq=1 ttl=102 time=80.6 ms
--- a-0001.a-msedge.net ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 80.608/80.608/80.608/0.000 ms
在节点上面进入容器的名称空间,使用tcpdump抓包。
[root@ip-172-31-53-61 ~]$ tcpdump -i any -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
09:09:18.172140 IP 172.31.48.162.46458 > 10.100.0.10.domain: 22082+ A? www.bing.com.default.svc.cluster.local. (56)
09:09:18.172181 IP 172.31.48.162.46458 > 10.100.0.10.domain: 59743+ AAAA? www.bing.com.default.svc.cluster.local. (56)
09:09:18.172406 IP 10.100.0.10.domain > 172.31.48.162.46458: 59743 NXDomain*- 0/1/0 (149)
09:09:18.172470 IP 10.100.0.10.domain > 172.31.48.162.46458: 22082 NXDomain*- 0/1/0 (149)
09:09:18.172513 IP 172.31.48.162.51210 > 10.100.0.10.domain: 59281+ A? www.bing.com.svc.cluster.local. (48)
09:09:18.172533 IP 172.31.48.162.51210 > 10.100.0.10.domain: 43411+ AAAA? www.bing.com.svc.cluster.local. (48)
09:09:18.172635 IP 10.100.0.10.domain > 172.31.48.162.51210: 43411 NXDomain*- 0/1/0 (141)
09:09:18.172707 IP 10.100.0.10.domain > 172.31.48.162.51210: 59281 NXDomain*- 0/1/0 (141)
09:09:18.172743 IP 172.31.48.162.36420 > 10.100.0.10.domain: 41442+ A? www.bing.com.cluster.local. (44)
09:09:18.172773 IP 172.31.48.162.36420 > 10.100.0.10.domain: 6893+ AAAA? www.bing.com.cluster.local. (44)
09:09:18.172947 IP 10.100.0.10.domain > 172.31.48.162.36420: 41442 NXDomain*- 0/1/0 (137)
09:09:18.172985 IP 10.100.0.10.domain > 172.31.48.162.36420: 6893 NXDomain*- 0/1/0 (137)
09:09:18.173030 IP 172.31.48.162.54253 > 10.100.0.10.domain: 9603+ A? www.bing.com.cn-north-1.compute.internal. (58)
09:09:18.173053 IP 172.31.48.162.54253 > 10.100.0.10.domain: 61573+ AAAA? www.bing.com.cn-north-1.compute.internal. (58)
09:09:18.173130 IP 10.100.0.10.domain > 172.31.48.162.54253: 9603 NXDomain* 0/1/0 (173)
09:09:18.173863 IP 10.100.0.10.domain > 172.31.48.162.54253: 61573 NXDomain 0/1/0 (173)
09:09:18.173893 IP 172.31.48.162.49537 > 10.100.0.10.domain: 64334+ A? www.bing.com. (30)
09:09:18.173941 IP 172.31.48.162.49537 > 10.100.0.10.domain: 31567+ AAAA? www.bing.com. (30)
09:09:18.174269 IP 10.100.0.10.domain > 172.31.48.162.49537: 64334 5/0/0 CNAME www-www.bing.com.trafficmanager.net., CNAME cn-bing-com.cn.a-0001.a-msedge.net., CNAME a-0001.a-msedge.net., A 13.107.21.200, A 204.79.197.200 (311)
09:09:18.174345 IP 10.100.0.10.domain > 172.31.48.162.49537: 31567 3/1/0 CNAME www-www.bing.com.trafficmanager.net., CNAME cn-bing-com.cn.a-0001.a-msedge.net., CNAME a-0001.a-msedge.net. (325)
09:09:18.174537 IP 172.31.48.162 > 13.107.21.200: ICMP echo request, id 45375, seq 1, length 64
09:09:18.255142 IP 13.107.21.200 > 172.31.48.162: ICMP echo reply, id 45375, seq 1, length 64
退出的方式直接使用exit即可, 就回到了host本身的ns里面。
源地址检查造成丢包的分析
问题网络访问路径:Client –> NLB –> Application Pod
特别的部分:NLB 开启了保留源地址就意味着 NLB 在转发网络流量的时候不会改变数据包五元组内的SourceIP, 这时候对于后端的Pod和节点来说, 收到的数据包的ip地址来源直接是Client 的IP 地址, 这会导致所有的流量其实都是来自于VPC之外的。 NLB在这其中变成了一个透明代理。从 NLB 发到后端application pod 中的流量会有偶尔timeout的情况, 并不是所有的请求都会timeout ,从客户端抓包显示tcp握手的时候就没有成功, 第一个syn包出去就一直没有回复,然后继续重发等待。 由于后端的pod比较多, 并且nlb在四层做了负载均衡,很难定位到某次的请求具体到了哪个后端pod上面。
写下这些的时候我已经知道了问题的答案是由于 VPC CNI 的一个 env , AWS_VPC_K8S_CNI_EXTERNALSNAT 会指定是否做 SNAT, 比较早的版本, cni 插件没有对 SNAT 在iptables上面进行标记和处理, 这样会导致 过不了操作系统的网络报文地址校验, 进而导致丢包。关于 linux 的数据包源地址校验,也就是 rp_filter 的参数, 在EKS中默认都是1 。
rp_filter参数用于控制系统是否开启对数据包源地址的校验。rp_filter参数有三个值,0、1、2,具体含义:0:不开启源地址校验。1:开启严格的反向路径校验。对每个进来的数据包,校验其反向路径是否是最佳路径。如果反向路径不是最佳路径,则直接丢弃该数据包。2:开启松散的反向路径校验。对每个进来的数据包,校验其源地址是否可达,即反向路径是否能通(通过任意网口),如果反向路径不同,则直接丢弃该数据包。
默认的情况下, 这个参数是1, 因此 :数据包发到了eth1网卡,如果这时候开启了rp_filter参数,并配置为1,则系统会严格校验数据包的反向路径。从路由表中可以看,返回响应时数据包要从eth0网卡出,即请求数据包进的网卡和响应数据包出的网卡不是同一个网卡,这时候系统会判断该反向路径不是最佳路径,而直接丢弃该请求数据包。
排查路由表 和 Iptables当 AWS_VPC_K8S_CNI_EXTERNALSNAT 为 False 的时候查看节点的路由rule:
[root@ip-172-31-53-61 ~]# ip rule ls
0: from all lookup local
512: from all to 172.31.49.222 lookup main
512: from all to 172.31.52.222 lookup main
512: from all to 172.31.59.203 lookup main
512: from all to 172.31.61.61 lookup main
512: from all to 172.31.49.246 lookup main
512: from all to 172.31.58.47 lookup main
512: from all to 172.31.53.79 lookup main
512: from all to 172.31.63.97 lookup main
512: from all to 172.31.53.74 lookup main
512: from all to 172.31.54.196 lookup main
512: from all to 172.31.51.218 lookup main
512: from all to 172.31.63.248 lookup main
512: from all to 172.31.54.200 lookup main
512: from all to 172.31.51.108 lookup main
512: from all to 172.31.56.137 lookup main
512: from all to 172.31.54.85 lookup main
512: from all to 172.31.51.82 lookup main
512: from all to 172.31.57.72 lookup main
512: from all to 172.31.59.200 lookup main
512: from all to 172.31.58.18 lookup main
512: from all to 172.31.55.235 lookup main
512: from all to 172.31.48.162 lookup main
512: from all to 172.31.60.128 lookup main
512: from all to 172.31.50.246 lookup main
512: from all to 172.31.61.216 lookup main
512: from all to 172.31.55.130 lookup main
512: from all to 172.31.49.208 lookup main
512: from all to 172.31.55.135 lookup main
512: from all to 172.31.50.208 lookup main
512: from all to 172.31.63.121 lookup main
512: from all to 172.31.52.205 lookup main
512: from all to 172.31.52.71 lookup main
512: from all to 172.31.51.7 lookup main
512: from all to 172.31.53.238 lookup main
1024: from all fwmark 0x80/0x80 lookup main
1536: from 172.31.56.137 lookup 2
1536: from 172.31.54.85 lookup 2
1536: from 172.31.51.82 lookup 2
1536: from 172.31.57.72 lookup 2
1536: from 172.31.59.200 lookup 2
1536: from 172.31.58.18 lookup 2
1536: from 172.31.55.235 lookup 2
1536: from 172.31.48.162 lookup 2
1536: from 172.31.60.128 lookup 2
1536: from 172.31.50.246 lookup 2
1536: from 172.31.61.216 lookup 2
1536: from 172.31.55.130 lookup 2
1536: from 172.31.49.208 lookup 2
1536: from 172.31.55.135 lookup 2
1536: from 172.31.50.208 lookup 3
1536: from 172.31.63.121 lookup 3
1536: from 172.31.52.205 lookup 3
1536: from 172.31.52.71 lookup 3
1536: from 172.31.51.7 lookup 3
1536: from 172.31.53.238 lookup 3
32766: from all lookup main
32767: from all lookup default
路由表 main:
[root@ip-172-31-53-61 ~]# ip r s table main
default via 172.31.48.1 dev eth0
169.254.169.254 dev eth0
172.31.48.0/20 dev eth0 proto kernel scope link src 172.31.53.61
172.31.48.162 dev enicfd09b318e8 scope link
172.31.49.208 dev eni3512a649bfb scope link
172.31.49.222 dev eni8cf9e51b58a scope link
172.31.49.246 dev eni9f41e641d45 scope link
172.31.50.208 dev eniffd28bfda2d scope link
172.31.50.246 dev eni1abad8afd57 scope link
172.31.51.7 dev eni76e381844d3 scope link
172.31.51.82 dev eni524077fd828 scope link
172.31.51.108 dev eni08e24263c30 scope link
172.31.51.218 dev enicb4edb90122 scope link
172.31.52.71 dev eni61a9554ce92 scope link
172.31.52.205 dev eniabe0e0a95e5 scope link
172.31.52.222 dev eni60eac028c5b scope link
172.31.53.74 dev enibecb9c399f8 scope link
172.31.53.79 dev eni6c5800d82af scope link
172.31.53.238 dev eni5a413534f4e scope link
172.31.54.85 dev eni2acd4947ff6 scope link
172.31.54.196 dev eni54f6d6a6254 scope link
172.31.54.200 dev eni47a45758006 scope link
172.31.55.130 dev eni1658effeb9c scope link
172.31.55.135 dev enibe97b10ca0d scope link
172.31.55.235 dev eni179f5c3696c scope link
172.31.56.137 dev eni099fbf41bd0 scope link
172.31.57.72 dev eni10574b2dfef scope link
172.31.58.18 dev eni5434103f7b9 scope link
172.31.58.47 dev enif4a18529a5f scope link
172.31.59.200 dev eni308c9b2c04f scope link
172.31.59.203 dev enia94f8f21d94 scope link
172.31.60.128 dev eni11239f98883 scope link
172.31.61.61 dev eni84312c21e65 scope link
172.31.61.216 dev enid75abf4f5e0 scope link
172.31.63.97 dev eni3ea3753c729 scope link
172.31.63.121 dev eni8bac6c0ff3f scope link
172.31.63.248 dev enie5c85d50c09 scope link
查看 table 3 的内容:
[root@ip-172-31 ...
配置自管理的Tailscale网络
Tailscale 虽然是 mesh 的网络模式, 可以点对点的连接所有设备, 能直连会尽量直接连接, 然鹅还是需要一个默认的server来进行服务发现和临时中转流量.
那么大概的配置框架就已经出现了, 一个服务发现中心, 和多个不同的客户端.开始的时候直接使用的tailscale + github账户登录的方式使用, 然后发现 github 账户直接托管的中心服务不能关闭国外的中转服务器, 这就比较难受, 本来可以直通的线路走了国外的中转不稳定, 会断, 最后还是走国内的便宜云服务器自己维护了一个开源的headscale作为中心服务.
大概的步骤如下吧:
安装headscale官方文档
现在的 docker 的版本是有问题的。。。。别用
我准备了这些:
域名, 域名证书
一台debian的云服务器
公网ip地址
具体的安装步骤就是按照官方网站走下来就可以了.需要注意的地方就是备案, 不备案会导致无法使用 443, 那么需要在tailscale的配置文件中指定端口, 让tailscale 监听在一个不常用的端口上.记录一下命令, 我因为没有写清楚 server 的地址和端口, 折腾了一天… 一度怀疑是不是换端口也不行, 必须备案 …
配置文件headscale ~$ vim /etc/headscale/config.yaml
# 大约在配置文件的 13行左右.
server_url 这个字段需要写成 https://YOURHOSTNAME.YOURDOMAIN:PORT 就可以了.
大约在配置文件的77行左右, 会有一个 DEPR 集成的服务, 开启这个服务之后, 可以使用当前的服务器直接作为DEPR中转节点, 我开了.
77 derp:
78 server:
79 # If enabled, runs the embedded DERP server and merges it into the rest of the DERP config
80 # The Headscale server_url defined above MUST be using https, DERP requires TLS to be in place
81 enabled: true
绑定证书的位置在大约 151行之后, 我使用自己签发的证书, 就是直接配置 182 183 两行的参数就行.
181 ## Use already defined certificates:
182 tls_key_path: /path/to/cert.key
183 tls_cert_path: /path/to/cert.pem
安装tailscale客户端按照安装文档直接安装, 不一样的发行版(是的, Windows 也是 Linux 发行版) 安装方式不同, 基本上启动之后都能用, 完成度非常高.
注册节点的命令节点注册命令记录.
sudo tailscale up --accept-dns=false --advertise-exit-node --advertise-routes=192.168.31.0/24 --login-server=https://YOURHOSTNAME.YOURDOMAIN:PORT --accept-routes
# 也可以是:
sudo tailscale up --accept-dns=false --advertise-exit-node --login-server=https://YOURHOSTNAME.YOURDOMAIN:PORT --accept-routes
# 或者是:
sudo tailscale up --accept-dns=false --login-server=https://YOURHOSTNAME.YOURDOMAIN:PORT --accept-routes
# 最后是:
sudo tailscale up --accept-dns=true --login-server=https://YOURHOSTNAME.YOURDOMAIN:PORT --accept-routes
这个命令执行完毕之后, 会返回一个网页, 网页打开里面有一个命令, 复制命令去 headscale 服务器的命令行(bash)里面执行一下,节点就注册进来了.
更新现在已经存在的设置最近需要更新我的一个节点, 发布 VPC内的 CIDR 块, 这个设置之前没有 advertise-route, 已经跑了很久, 是是否更新一下了 。这个实例在我的默认VPC里面, 这样的话这个实例就直接变成了这个VPC内的IGW, 流量会通过这个实例发送到VPC内, 试了一下, 可以直接将这个网络范围内的DNS指向VPC内的.2, 甚至可以直接在家用 EFS 这类的东西了.
当然, 如果节点需要变动之前运行的参数, 是需要给出和之前一致的参数, 然后添加 或者 变更其中的一部分的.
sudo tailscale up --accept-dns=false --advertise-exit-node --login-server=https://YOURHOSTNAME.YOURDOMAIN:PORT --accept-routes --advertise-routes=172.31.0.0/16
archlinux 使用 tailscale + Sunshine 串流
接上面的测试, 既然显卡都已经能用了, 为啥不能直接启动一个steam呢? 于是。。。
安装的步骤比较简单:
# Sunshine 用来作为 stream hosting
sudo pacman -S sunshine
# Steam 以及 Steam-navtive 是 steam 的runtime, ttf 是为了可以正常的显示中文字体, 好像字体上面是最常见的问题, 比如显示出来是一堆方块。
sudo pacman -S steam-native-runtime
sudo pacman -S steam ttf-liberation
这些安装完成之后我自己直接 drun 去调用 steam 就可以了。
启动使用的desktop 文件叫作 steam(native) 启动之后登录, 然后可以正常下载游戏了。
默认可以下载的游戏都是原生支持linux的, 不支持的可以在steam的设置里面打开proton兼容, 之后steam的界面上就不会区分任何平台了。
手柄支持手柄默认不能传递到hosting, sunshine 的启动日志里面有报错:
[2023:12:27:21:35:33]: Error: Could not create Sunshine Gamepad: Permission denied
[2023:12:27:21:35:33]: Error: Could not create Sunshine Gamepad: Permission denied
给予这个报错的搜索结果有两个:
添加当前的用户到 input 组里面 usermod -a -G input ec2-user
# checking
groups ec2-user
第二个方案是, 确保自己的内核装载 uinput 模块。 modprobe uinput
同时还在文档里面找到了另一个地方,需要配置一个 udev ruleecho 'KERNEL=="uinput", SUBSYSTEM=="misc", OPTIONS+="static_node=uinput", TAG+="uaccess"' | \
sudo tee /etc/udev/rules.d/85-sunshine.rules
或者这文档 以及这个Issue
我目前不太确定具体哪个是正确的, 因为重启这个实例的时候把tailscale给玩儿没了.. 现在连不上了…闹心
Redis 笔记
ElastiCache主要概念
ElastiCache nodesA node is the smallest building block of an ElastiCache deployment.node is a fixed-size chunk of secure, network-attached RAM.总结来说, 就是ec2实例上面跑了相同版本的Engine for Redis。
ElastiCache for Redis shards
A Redis shard (called a node group in the API and CLI) is a grouping of one to six related nodes. A Redis (cluster mode disabled) cluster always has one shard.Redis (cluster mode enabled) clusters can have up to 500 shards, with your data partitioned across the shards.
Shard 是多个 Nodes 的集合, 或者叫作节点组. 一个Shard包括的节点有不同的角色, 一个Primary 和 最多5个 Replica.
ElastiCache for Redis clustersA Redis cluster is a logical grouping of one or more ElastiCache for Redis shards. Data is partitioned across the shards in a Redis (cluster mode enabled) cluster.集群模式关闭, 1 Cluster – 1 Shard – 1 - 6 Nodes: 1 Primary and 5 Nodes集群模式开启, 1 Cluster – 500 Shard – 1 - 6 Nodes: 1 Primary Per Shard
ElastiCache for Redis replicationRedis (cluster mode disabled) clusters support one shard (in the API and CLI, called a node group).Redis (cluster mode enabled) clusters can have up to 500 shards, with your data partitioned across the shards.
每个Replica都是Primary中全部数据的复制。 Replica使用异步的方式进行与Primary的数据同步。
第一次 psync2 全量复制所有内存当前存储的数据, 后续使用redis的增量复制。
AWS Regions and availability zones目前中国区不能使用 GlobalStore, 并且Region之间也是无法相互同步数据的。 在不同的az 之间可以做高可用来降低停机的时间。
ElastiCache for Redis endpointsAn endpoint is the unique address your application uses to connect to an ElastiCache node or cluster.
Redis 禁用集群模式的单节点端点单节点的集群端点用于读取和写入. In one word, Single Primary, read and write at one point.用这个节点的 Endpoint 即可。
Redis 禁用集群模式的多节点端点多节点有两个不同的端点, Primary 端点总是连接到Primary 节点,故障切换会切换这个dns指向的后端。Reader Endpoint 在所有的 Replica节点之间分流Connection 用来提供读取行为。
用控制台上面的 Primary Endpoint 和 Reader Endpoint
Redis 启用集群模式的端点集群模式下, 只是配置一个endpoint, 但是连接到Endpoint之后, 客户端可以发现所有的主节点和从节点。
** 用Configuration Endpoint 可以找到集群内部的每一个 Primary 和 Replica节点 **
ElastiCache parameter groupsCache parameter groups are an easy way to manage runtime settings for supported engine software. Parameters are used to control memory usage, eviction policies, item sizes, and more.
简单来说, 创建每一个配置文件在aws的控制台上, 可以调整一部分Redis的参数, 然后可能在集群内可以实时生效, 也可能需要触发一次Failover才能生效。elasticache的参数管理
通常来说, 改动了参数组中的几个参数可能会需要重启节点:
activerehashing
databases
ElastiCache for Redis securityPENDING… Maybe follow offical guide.
ElastiCache security groups创建集群的时候需要指定一个安全组, 需要放行 6379 port, DONE。
ElastiCache subnet groups子网组是运行 Redis 的所有子网的集合, 创建一个子网, 让托管的节点的把ENI放在这个子网里面, 私有子网。
ElastiCache for Redis backups备份特定时间的数据, 可以使用这个用来还原成新的集群, 或者是创建一个集群的种子, 备份中包括所有的data, 和一部分集群的metadata。bgsave 或者 forkless save, 这两个取决于是否有足够的内存空间, 当空间充足的时候使用的默认的 bgsave, 但是肯定的是, bhsave 会有性能的开销,所以最好是使用副本节点来创建备份或者快照。对于forkless本身是另一个机制,但是forkless会尝试delay 写入的延迟,从而确保不会积累过多的change 导致内存压力过大失败。
ElastiCache eventsPENDING… Maybe follow offical guide.
Redis 缓存穿透, 击穿 和 雪崩穿透主要是指异常的查询请求, 缓存未命中的场景下直接访问后端, 后端承载了大量请求导致的崩溃。目前看到需要两个条件:
数据在缓存层未命中。
大量的请求转移到了后端。
请求的数据可能在缓存层 以及 后端都不存在。
避免的方法可能有:
在redis 前面添加一个 BloomFilter, 在请求进来的时候进行过滤, 对于异常的请求直接拒绝或者返回一个NULL。
提前缓存一部分数值为 NULL 的数据, 在缓存层直接接下这些请求。这个本身是有点问题的。
击穿这个概念是指的 少部分热点数据被大量的查询时候, 数据突然从缓存中消失, 可能是过期也可能删除等等, 这样有大量的相同请求发送到后端。解决方案:
设置部分数据永远不过期。
后端进行加分布式锁。
雪崩批量的热数据过期, 这时候大部分的请求可能还在继续尝试查询不同的数据,直接将这些请求发送到了后端的数据库, 数据库崩了。解决方案:
创建多个实例, 和副本来提高可用性。
后端加锁限流。
调整过期时间, 让不同的数据过期的时间错开,防止批量的key 相同的时间过期。
总结起来就是, 避免缓存在特定的场景下失效, 想各种方法保护缓存的可用性。
More NoteCOB: Client Output Buffer, Primary 向 Replica 同步数据使用, Max Memory 没有计算这部分的内存, 使用的是Redis引擎之外的内存(os管理的内存)。
Policy : LRU 不严格, 随机选择三个。maxmemory-sample: 3, 可以调大。 sample越大, 信号的时间越长。
Reclaim策略里面, 每秒扫描200个key, 如果数据量比较大的话, Redis会进入loop阶段, 反复尝试Reclaim到25% 以下。
可以尝试使用 scan 命令扫描全部的数据, 遍历所有的key,这样会触发lazyway主动进行回收。扫描的指令:
scan 0 match * count 20000
LRU vs LFU
为了保持主从一致, primary 上过期或者删除的key, 会同步发送一个显式的 delete 指令, 这个会统计在replica的settypecmd。
snapshot里面的数据在恢复的时候,会检查key 的ttl , 如果超过会直接删除。在Redis内存与物理内存mapping由操作系统的虚拟内存管理器 和 指定的内存分配器进行处理。
关于Info指令的所有参数的解释:https://redis.io/commands/info/
localhost:6379> info memory
# Memory
used_memory:938464
used_memory_human:916.47K # Redis 存储数据的使用量
used_memory_rss:10747904
used_memory_rss_human:10.25M # Redis 常住内存集的用量
used_memory_peak:1134048
used_memory_peak_human:1.08M # Redis 的内存峰值
used_memory_peak_perc:82.75%
used_memory_overhead:888488
used_memory_startup:865904
used_memory_dataset:49976
used_memory_dataset_perc:68.88%
allocator_allocated:1479168 # 内存分配器已经分配的量
allocator_active:1601536
allocator_resident:4575232
total_system_memory:8182751232
total_system_memory_human:7.62G # 系统内存的总量
used_memory_lua:31744
used_memory_vm_eval:31744
used_memory_lua_human:31.00K # Lua 引擎的内存使用量
used_memory_scripts_eval:0
number_of_cached_scripts:0
number_of_functions:0
number_of_libraries:0
used_memory_vm_functions:32768
used_memory_vm_total:64512
used_memory_vm_total_human:63.00K
used_memory_functions:184
used_memory_scripts:184
used_memory_scripts_human:184B
maxmemory:0 # Max Memory 当前的配置
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.08
allocator_ ...
CFS 调度器资料
https://docs.kernel.org/scheduler/sched-design-CFS.htmlhttp://arthurchiao.art/blog/linux-cfs-design-and-implementation-zh/#11-cfs%E8%BF%9B%E7%A8%8Btask%E7%9A%84%E5%85%AC%E5%B9%B3%E8%B0%83%E5%BA%A6https://danluu.com/cgroup-throttling/https://heapdump.cn/article/4235306