archlinux 配置 xorg 使用 nvidia T4
最近的一个想法,基于 dd 到中国区域的 archlinux, 可以尝试直接改改 xorg, 用用 nvidia 的显卡。
大概折腾了一天, 记录一下步骤和过程。
之前使用的是 Xorg + DWM 的简单架构, 软件非常少。那么在这个软件的基础上启用显卡和配置xorgserver 使用显卡, 基本上就是这两部分。
安装显卡驱动
查看显卡信息> lspci
00:1e.0 3D controller: NVIDIA Corporation TU104GL [Tesla T4] (rev a1)
安装驱动直接参考archwiki , 一条命令搞定, 走dkms。安装的这个版本的闭源驱动。> pacman -Ss nvidia-dkms
extra/nvidia-dkms 545.29.06-1 [installed]
NVIDIA drivers - module sources
> pacman -S nvidia-utils
# 启动驱动程序的守护进程。
# 这个如果不开启的话, xrdp 调用 xorg server 的时候 启动会失败, 显示无法找到 nvidia module, 其实不是找不到, 只是由于没有图形化, 所以没有装载。
sudo systemctl enable nvidia-persistenced.service
# 调整显示的分辨率,目前还是手动调整的, 还在改配置文件。
> xrandr --output DVI-D-0 --mode 1920x1080 --rate 60
等pacman自己处理完dkms的模块编译之后, 重启os就可以看到nvidia模块被装载。> lsmod | grep nvidia
nvidia_uvm 3481600 0
nvidia_drm 118784 7
nvidia_modeset 1585152 6 nvidia_drm
nvidia 62402560 141 nvidia_uvm,nvidia_modeset
video 77824 1 nvidia_modeset
> modinfo nvidia
filename: /lib/modules/6.6.7-zen1-1-zen/updates/dkms/nvidia.ko.zst
alias: char-major-195-*
version: 545.29.06
supported: external
license: NVIDIA
firmware: nvidia/545.29.06/gsp_tu10x.bin
firmware: nvidia/545.29.06/gsp_ga10x.bin
srcversion: 8302209549E8FEAC029EDC0
alias: pci:v000010DEd*sv*sd*bc06sc80i00*
alias: pci:v000010DEd*sv*sd*bc03sc02i00*
alias: pci:v000010DEd*sv*sd*bc03sc00i00*
depends:
retpoline: Y
name: nvidia
vermagic: 6.6.7-zen1-1-zen SMP preempt mod_unload
配置xrdp
这里已经可以正常的驱动显卡, 但是xorg不会去调用显卡启动图形,查看了archwiki之后,发现如果使用 xrdp , 那么还需要重新安装 xrdp 的后端。 需要使用来自aur的后端来匹配nvidia显卡的支持, 而不是 archlinux 的主仓库里面的默认软件包, 使用 paru 进行的下面步骤。 aur 里面的 xorgxrdp,会自动拉取编译 xrdp-git, 因此这里的版本显示和 aur 仓库的不完全一致。> paru -Ss xrdp
aur/xorgxrdp-nvidia 0.2.18.r55.g3a4d465-1 [+4 ~0.00] [Installed]
Xorg drivers for xrdp, with NVIDIA GPU support.
aur/xrdp-git 0.9.18.r565.geb1c3cd4-1 [+30 ~0.01] [Installed: 0.9.18.r599.g9fbe0ad1-1]
An open source remote desktop protocol (RDP) server. Git version, devel branch.
安装完成之后, 需要重启一下系统。
编译安装aur的过程中,最后的步骤里面有一个红色的提示文字, 需要在配置中变更一下xrdp读取的xorg配置文件的位置。> cat -n /etc/xrdp/sesman.ini
130 [Xorg]
143 param=Xorg
144 ; Leave the rest parameters as-is unless you understand what will happen.
145 param=-config
; 下面的这两个, 启用nvida的配置文件,注释默认的。
; 这里配置的是启动xorg server 的时候读取的配置文件位置 以及 xorg server 的参数。
146 ; param=xrdp/xorg.conf
147 param=xrdp/xorg_nvidia.conf
148 param=-noreset
149 param=-nolisten
之后, 使用 nvidia 提供的 util , 生成一份nvidia显卡的的配置文件, merge 配置文件里面的这份。> nvidia-xconfig -c /etc/X11/xrdp/xorg_nvidia.conf
# 这里面可以不手动备份, 该命令会自动备份之前的配文件, 如果有不同的配置会自动merge。
最后,我在这样做完之后, 重启 xrdp , xorg 确实开始使用显卡了, 但是所有启动的程序不会使用显卡, 默认还是CPU在计算, 这是因为 xorg 的配置文件里面少了 FILE Section, 这个文件的位置可能会不同,我这边确实在这个位置, 文件存在的情况下直接拿来用了。Section "Files"
ModulePath "/usr/lib64/nvidia/xorg"
ModulePath "/usr/lib64/xorg/modules"
EndSection
参考了这个网页中的配置: https://forums.developer.nvidia.com/t/glxinfo-command-returning-badwindow-invalid-window-parameter-error/36172
最终的配置文件内容如下:/etc/X11/xrdp/xorg_nvidia.conf
> cat -n /etc/X11/xrdp/xorg_nvidia.conf
1 Section "ServerLayout"
2 Identifier "XRDP GPU Server"
3 Screen 0 "dGPU"
4 InputDevice "xrdpMouse" "CorePointer"
5 InputDevice "xrdpKeyboard" "CoreKeyboard"
6 EndSection
7
8 Section "ServerFlags"
9 # This line prevents "ServerLayout" sections in xorg.conf.d files
10 # overriding the "XRDP GPU Server" layout (xrdp #1784)
11 Option "DefaultServerLayout" "XRDP GPU Server"
12 Option "DontVTSwitch" "on"
13 Option "AutoAddDevices" "off"
14 EndSection
15
16 Section "Files"
17 ModulePath "/usr/lib64/nvidia/xorg"
18 ModulePath "/usr/lib64/xorg/modules"
19 EndSection
20
21 Section "Module"
22 Load "xorgxrdp"
23 EndSection
24
25 Section "InputDevice"
26 Identifier "xrdpKeyboard"
27 Driver "xrdpkeyb"
28 EndSection
29
30 Section "InputDevice"
31 Identifier "xrdpMouse"
32 Driver "xrdpmouse"
33 EndSection
34
35 Section "Screen"
36 Identifier "dGPU"
37 Device "dGPU"
38 Option "DPI" "96 x 96"
39 # T4 needs an entry here, this is not the desktop size
40 SubSection "Display"
41 Virtual 1920 1080
42 EndSubSection
43 EndSection
44
45 Section "Device"
46 Identifier "dGPU"
47 Driver "nvidia"
48 # T4 may need to comment out next line
49 # Option "UseDisplayDevice" "none"
50 Option "ConnectToAcpid" "false"
51 BusID "PCI:0:30:0"
52 EndSection
排查思路 和 日志的位置。
首先查看 xrdp 的 status, 是不是正常。
排查日志 /var/log/xrdp.log , 这里面记录的是 xrdp 的启动的过程。
如果没有错误, 那么查看 /var/log/xrdp-sesman.log, 这里面会记录xorg启动的命令和 xorg 的状态。 可以把日志里面记录的命令复制出来手动执行,直接看命令的输出; 或者查看 xorg 的日志, 看看历史记录了什么错误。[2023-12-21T16:50:17.711+0800] [INFO ] Socket 13: connection ac ...
查看EKS集群节点上的容器和ENI的对应关系
版本信息root@ip-172-31-35-61 ~ [1]# containerd -v
containerd github.com/containerd/containerd v1.6.16 31aa4358a36870b21a992d3ad2bef29e1d693bec.m
root@ip-172-31-35-61 ~# uname -a
Linux ip-172-31-35-61.cn-north-1.compute.internal 6.1.10-arch1-1 #1 SMP PREEMPT_DYNAMIC Mon, 06 Feb 2023 09:28:04 +0000 x86_64 GNU/Linux
root@ip-172-31-35-60 ~ [1]# kubelet --version
Kubernetes v1.24.9-eks-49d8fe8
容器虚拟网卡和节点网卡的关主要的思路是通过veth的id 。
找到 Pod 的 Pause 容器
root@ip-172-31-35-61 ~# nerdctl -n k8s.io ps | grep -v pause
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
218279edbee1 918309763551.dkr.ecr.cn-north-1.amazonaws.com.cn/eks/kube-proxy:v1.24.9-minimal-eksbuild.1 "kube-proxy --v=2 --…" 14 hours ago Up k8s://kube-system/kube-proxy-kqlj2/kube-proxy
3a8aaf963501 123456123456.dkr.ecr.cn-north-1.amazonaws.com.cn/haydenarchlinux:latest "sleep 365d" 8 minutes ago Up k8s://default/haydenarch-77c4f7cff9-dxsps/haydenarch
进入容器内部查看网卡的ID
root@ip-172-31-35-61 ~# nerdctl -n k8s.io exec -it 3a8aaf963501 fish
root@haydenarch-77c4f7cff9-dxsps /# cat /sys/class/net/eth0/iflink
54
root@haydenarch-77c4f7cff9-dxsps /# ip ad
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
3: eth0@if54: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
link/ether 66:3a:fb:f2:00:b2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.31.39.84/32 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::643a:fbff:fef2:b2/64 scope link
valid_lft forever preferred_lft forever
在实例上面查看 网卡的信息, 找到带有 id 54 的虚拟网卡对。
root@ip-172-31-35-61 ~# ip ad | grep 54
54: enid573ff579e6@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
查看这个虚拟网卡的全部信息, 可以看到 link-netns, 这是容器的Network NameSpace。
```shell
root@ip-172-31-35-61 ~ [1]# ip link show enid573ff579e6
54: enid573ff579e6@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP mode DEFAULT group default
link/ether 36:06:dc:85:42:a4 brd ff:ff:ff:ff:ff:ff link-netns cni-bb451da7-00be-2d59-b5e0-1dd4e77565e8
可以使用下面的命令查看所有的ns并找到对应的id。
root@ip-172-31-35-61 ~# ip netns list
cni-2e29d022-09f4-6626-f416-29cfb9652e78 (id: 13)
cni-e5be29a1-d111-53ec-8f88-94118eb1466c (id: 10)
cni-bb451da7-00be-2d59-b5e0-1dd4e77565e8 (id: 8) # 这个就是
cni-673e1c4b-acd1-ab7e-b374-1a4192eea86e (id: 6)
cni-1207e72f-e68e-a7e7-161e-979e9e9ada7a (id: 5)
cni-a8b7807f-a37e-dd4e-98cb-9d3e7cd42f11 (id: 4)
cni-08a7a0e2-8e33-b669-83ee-75957676ffbb (id: 3)
cni-8a26c501-2ea9-f4be-36ae-745a5c307fbc (id: 0)
cni-2598e89a-d2ba-38a8-6412-92fbff32871b (id: 9)
cni-817961be-8d28-b32c-816f-a842b9d243fe (id: 2)
cni-a84561aa-8668-8b7c-4b5e-56568e14dc83 (id: 12)
cni-5de27d6e-c311-6ee3-4ed5-85b2a05b6943 (id: 11)
cni-d102a5e6-d6ea-fb90-2ac8-a97cd8df9c85 (id: 7)
cni-88bf7480-bdd6-e063-3103-894d29b16302 (id: 1)
可以直接进入pod 的network ns 查看容器的网络信息, 这和上面在容器内直接看到的信息是一致的。
root@ip-172-31-35-61 ~ [1]# ip netns exec cni-bb451da7-00be-2d59-b5e0-1dd4e77565e8 ip ad
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
3: eth0@if54: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
link/ether 66:3a:fb:f2:00:b2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.31.39.84/32 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::643a:fbff:fef2:b2/64 scope link
valid_lft forever preferred_lft forever
如何确定容器的网卡绑定在了哪个ENI上面由于VPC CNI本身的实现, 在EKS的节点上面会出现多的ENI,具体pod的流量是怎么走向eth网卡的,去了eth0 还是 eth1 或者其他的网卡, 需要通过路由条目来确定。和上面的记录时间不同, 所以这个部分的记录,是另一个节点的另一个容器了, ip地址会不一致。
查看容器的IP地址
> kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
haydenarch-7d9ff55cbd-4b7pl 1/1 Running 0 18h 172.31.55.218 ip-172-31-55-30.cn-north-1.compute.internal <none> <none>
查看节点的路由表, 看看这个ip地址的路由信息。
[root@ip-172-31-55-30 ~]# ip rule list | grep 172.31.55.218
512: from all to 172.31.55.218 lookup main
1536: from 172.31.55.218 lookup 2
那么上面的结果显示, 这个IP地址的数据包会查 table 2, 查看 table 2
[root@ip-172-31-55-30 ~]# ip r s table 2
default via 172.31.48.1 dev eth1
172.31.48.1 dev eth1 scope link
观察的这个容器现在是在 eth1 上面的, 查看节点的网卡信息。
[root@ip-172-31-55-30 ~]# ip ad s eth1
17 ...
自管理节点加入集群
添加一个自管理的节点
创建集群,启动一个新的 EC2, 登录到已经启动的 EKS 优化 OS 内,准备复制一些脚本过来。
添加EC2的标签: kubernetes.io/cluster/clusterName owned
配置EC2的Instance Profile
控制台获取 Kubernetes APIServer的Endpoint URL
获取 apiserver b64 CA : cat ~/.kube/config 这个文件里面可以找到 ,或者是通过EKS的控制台上面, 找到 Base64 的 CA。
编辑 userdata, 或者 ssh 登录到ec2上面创建一个bash脚本用来调用 bootstrap.sh
mkdir ~/eks; touch ~/eks/start.sh
---
#!/bin/bash
set -ex
B64_CLUSTER_CA=
API_SERVER_URL=
K8S_CLUSTER_DNS_IP=10.100.0.10
/etc/eks/bootstrap.sh ${ClusterName} --b64-cluster-ca ${B64_CLUSTER_CA} --apiserver-endpoint ${API_SERVER_URL}
集群里面没有节点组 , 也不会创建aws-auth configmap 所以节点无法正常的加入集群, 需要手动创建。
apiVersion: v1
data:
mapRoles: |
- groups:
- system:bootstrappers
- system:nodes
rolearn: [CLUSTER_ROLE]
username: system:node:{{EC2PrivateDNSName}}
mapUsers: |
[]
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
需要复制的文件sudo pacman -S containerd # 安装Containerd
scp /etc/eks/bootstrap.sh root@54.222.253.235:/etc/eks/bootstrap.sh # 复制bootstrap
scp /usr/bin/imds root@54.222.253.235:/usr/bin/imds # shell 脚本, 用来帮忙调用ec2 metadata 获取实例和VPC子网的信息
scp -pr /etc/eks/ root@54.222.253.235:/etc/eks/ # 直接复制了eks的相关脚本和配置模板
scp -pr /var/lib/kubelet/kubeconfig root@54.222.253.235:/var/lib/kubelet/kubeconfig # 复制kubeletconfig配置文件模板
scp -pr /etc/kubernetes/ root@54.222.253.235:/etc/kubernetes/ # 复制 kubernetes 的配置文件
scp -pr /etc/kubernetes/kubelet/ root@54.222.253.235:/etc/kubernetes/kubelet/ # 上面的命令没有递归复制, 所以需要指定
# 设置对应的内核参数, 如果不做kubelet 会报错提示 这些参数不符合要求。
kernel.panic = 10
kernel.panic_on_oops = 1
vm.overcommit_memory = 1
Bootstrap 脚本内容记录一下脚本自动配置的内容, 大概就是 获取变量, aws的服务地址, ec2 元数据地址, 替换模板中的变量生成Kubelet配置文件 和 Containerd 的配置文件(这个替换是一次性的, 也就是说, bootstrap只能变更模板中的变量一次, 第二次执行只会生成刷新一次集群的信息, 以及重启服务)。
读取bootstrap后面给出的参数,设置变量, 例如: ClusterName etc.
查看Kubelet的版本, 决定Runtime, containerd | dockerd, 判断条件是 kubelet 版本 大于 1.24++ kubelet --version
++ grep -Eo '[0-9]\.[0-9]+\.[0-9]+'
+ KUBELET_VERSION=1.24.9
---
+ IS_124_OR_GREATER=true
+ DEFAULT_CONTAINER_RUNTIME=containerd
设置ECR以及Pause容器地址# 获取region以及aws service domain
+ AWS_DEFAULT_REGION=cn-north-1
+ AWS_SERVICES_DOMAIN=amazonaws.com.cn
# 调用脚本 /etc/eks/get-ecr-uri.sh cn-north-1 amazonaws.com.cn ''
+ ECR_URI=918309763551.dkr.ecr.cn-north-1.amazonaws.com.cn
+ PAUSE_CONTAINER_IMAGE=918309763551.dkr.ecr.cn-north-1.amazonaws.com.cn/eks/pause
+ PAUSE_CONTAINER=918309763551.dkr.ecr.cn-north-1.amazonaws.com.cn/eks/pause:3.5
+ CA_CERTIFICATE_DIRECTORY=/etc/kubernetes/pki
+ CA_CERTIFICATE_FILE_PATH=/etc/kubernetes/pki/ca.crt
创建证书目录:+ mkdir -p /etc/kubernetes/pki
+ sed -i s,MASTER_ENDPOINT,https://CE0253A94B6B14215AE3282580CFA5E3.yl4.cn-north-1.eks.amazonaws.com.cn,g /var/lib/kubelet/kubeconfig
+ sed -i s,AWS_REGION,cn-north-1,g /var/lib/kubelet/kubeconfig
+ sed -i s,CLUSTER_NAME,NewClusterForManualJoin,g /var/lib/kubelet/kubeconfig
获取 VPC CIDR# imds shell script help to get metadata.
imds: /usr/bin/imds
++ imds latest/meta-data/local-ipv4
++ imds latest/meta-data/network/interfaces/macs/02:66:06:2e:48:08/vpc-ipv4-cidr-blocks
创建kubelet 配置, 计算预留的资源 和 MaxPod 等等参数的数值。/etc/kubernetes/kubelet/kubelet-config.json
+ mkdir -p /etc/systemd/system/kubelet.service.d
+ sudo mkdir -p /etc/containerd
+ sudo mkdir -p /etc/cni/net.d
+ sudo mkdir -p /etc/systemd/system/containerd.service.d
创建containerd 配置文件+ printf '[Service]\nSlice=runtime.slice\n'
+ sudo tee /etc/systemd/system/containerd.service.d/00-runtime-slice.conf
+ sudo sed -i s,SANDBOX_IMAGE,918309763551.dkr.ecr.cn-north-1.amazonaws.com.cn/eks/pause:3.5,g /etc/eks/containerd/containerd-config.toml
kubelet配置和启动。+ sudo cp -v /etc/eks/containerd/kubelet-containerd.service /etc/systemd/system/kubelet.service
+ sudo chown root:root /etc/systemd/system/kubelet.service
+ sudo containerd config dump
+ systemctl enable kubelet
+ systemctl start kubelet
Filebeat 输出日志到 Opensearch
这个最后基本上可以确认是一个兼容性问题,测试完成发现, 开启兼容模式的Opensearch+filebeat的组合, filebeat 还是会不定期重启。
背景需求是,使用ES + filebeat 模式在收集日志。使用Supervisor作为容器的主进程管理工具,启动后分别运行 应用(这里用nginx代替) + filebeat
现在想要用ECS Fargate, 然后依旧还是这个模式, 尽可能新的变动之前的架构, ES 替换成 OpenSearch。
按照这个路数测试。
创建Opensearch版本:OpenSearch 2.11 (latest)OpenSearch_2_11_R20231113-P1 (latest)Availability Zone(s)1-AZ without standby
构建Supervisor管理的容器创建 Dockerfile创建dockerfile的部分, 比较难的是 , 需要找到合适的filebeat版本参考页面: Agents and ingestion tools其他的步骤就下载安装就可以.
# 使用官方Nginx作为基础镜像
FROM reg.liarlee.site/docker.io/nginx
# 安装Supervisor
RUN apt-get update && apt-get install -y supervisor
RUN mkdir -p /var/log/supervisor
RUN mkdir -p /etc/filebeat/
#RUN curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.11.3-amd64.deb && dpkg -i filebeat-8.11.3-amd64.deb
RUN curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-oss-7.12.1-amd64.deb && dpkg -i filebeat-oss-7.12.1-amd64.deb
COPY filebeat.yml /etc/filebeat/filebeat.yml
COPY nginx.conf /etc/nginx/nginx.conf
# 将Supervisor配置文件复制到容器中
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# 启动Supervisor来管理Nginx进程
CMD [ "/usr/bin/supervisord", "-n" ]
准备配置文件需要准备的配置文件一共3个:
supervisord.conf supervisor的管理配置, 决定了那些进程被管理。
> cat ./supervisord.conf
[unix_http_server]
file=/var/run/supervisor.sock ; (the path to the socket file)
chmod=0700 ; socket file mode (default 0700)
chown=nobody:nogroup ; socket file uid:gid owner
[supervisord]
logfile_maxbytes=50MB ; 日志文件的最大大小
logfile_backups=10 ; 日志文件的备份数
loglevel=info ; 日志级别
nodaemon=false ; 是否以守护进程模式启动Supervisor
minfds=1024 ; 可以打开的文件描述符的最小数量
minprocs=200 ; 可以创建的进程的最小数量
[program:nginx]
command=/usr/sbin/nginx -g "daemon off;" ; 启动Nginx的命令
autostart=true ; 在Supervisor启动时自动启动
autorestart=true ; 程序异常退出后自动重启
stderr_logfile=/var/log/nginx/error.log ; 错误日志文件路径
stdout_logfile=/var/log/access.log ; 访问日志文件路径
[program:filebeat]
command=/usr/bin/filebeat -e -c /etc/filebeat/filebeat.yml ; 启动Filebeat的命令
autostart=true
autorestart=true
stderr_logfile=/var/log/filebeat.err.log
stdout_logfile=/var/log/filebeat.out.log
filebeat.yml filebeat的配置文件。 这配置文件 GPT 会直接写出一个可以用 output.opensearch:, 其实还是不能的, 只能使用原本的配置文件。 (也许是我选择的filebeats版本不正确, 所以不行吧
filebeat本身是es序列里面的产品, 不支持opensearch也合理, 如果写成opensearch 会找不到output 的定义, 也说明并不支持这个字段。
2023-12-14T12:03:12.560Z INFO [publisher_pipeline_output] pipeline/output.go:145 Attempting to reconnect to backoff(elasticsearch(https://vpc-ecs-nginx-opensearch-qt7m5rmhddggkiuapyybcmz5oe.cn-north-1.es.amazonaws.com.cn:443)) with 7 reconnect attempt(s)
```shell
> cat ./filebeat.yml
filebeat.inputs:
- type: filestream
id: nginxaccesslog
paths:
- /var/log/access.log
fields:
log_type: access
seccomp.enabled: false # 这个不关闭的话可能会是一个干扰。
logging.level: debug # 由于调试方便设置了DEBUG。
# 这个配置段是关闭 xpack, xpack功能只在es里面提供, 商业版本。
ilm.enabled: false
setup.ilm.enabled: false
setup.pack.security.enabled: false
setup.xpack.graph.enabled: false
setup.xpack.watcher.enabled: false
setup.xpack.monitoring.enabled: false
setup.xpack.reporting.enabled: false
# output就是还用es
output.elasticsearch:
enable: true
hosts: ["vpc-ecs-nginx-opensearch-qt7m5rmhddggkiuapyybcmz5oe.cn-north-1.es.amazonaws.com.cn:443"] # 这个部分需要手动指定443, 因为是es的默认配置, 所以直接去 9200,就会连接不上.
protocol: "https"
xpack 报错的日志大概是这样的:
2023-12-14T12:03:12.560Z ERROR [publisher_pipeline_output] pipeline/output.go:154 Failed to connect to backoff(elasticsearch(https://vpc-ecs-nginx-opensearch-qt7m5rmhddggkiuapyybcmz5oe.cn-north-1.es.amazonaws.com.cn:443)): Connection marked as failed because the onConnect callback failed: request checking for ILM availability failed: 401 Unauthorized: {“Message”:”Your request: ‘/_xpack’ is not allowed.”} 2023-12-14T12:03:12.560Z INFO [publisher_pipeline_output] pipeline/output.go:145 Attempting to reconnect to backoff(elasticsearch(https://vpc-ecs-nginx-opensearch-qt7m5rmhddggkiuapyybcmz5oe.cn-north-1.es.amazonaws.com.cn:443)) with 7 reconnect attempt(s)
nginx.conf 这个是nginx 应用文件, 模拟一个应用程序, 提供webserver服务。配置文件就是标准的配置文件, 修改一下日志输出的路径. access_log /var/log/access.log main;
由于baseimage用的是nginx的, 所以nginx 的日志输出会软链接到/dev/stdout, filebeat 不收软链接的文件, 开了DEBUG会看到跳过这个文件的日志.
Buildstage接下来就可以Build镜像然后进行测试了。
> dive build -t reg.liarlee.site/library/superv-nginx:v31 .
> docker push reg.liarlee.site/library/superv-nginx:v31
> docker run -it --name superv-nginx --rm reg.liarlee.site/library/superv-nginx:v31
运行启动之后可以看到输出的日志是:
2023-12-14 14:03:31,093 INFO success: filebeat entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2023-12-14 14:03:31,093 INFO success: nginx entered ...
Windows Core EKS 节点管理命令
windows 查看磁盘空间的使用情况:
Get-PSDrive -Name C | Select-Object Name, Free
windows 实例的磁盘空间扩容
diskpart
list volume
select volume 0
extend
从ecr下载镜像
$ecrCreds = (Get-ECRLoginCommand).password
Write-Host $ecrCreds
ctr -n k8s.io image pull -u AWS:$ecrCreds ecr link
pull image 需要使用节点的C盘空间, 在节点的磁盘空间不足的情况下,会报错。
rpc error: code = Unknown desc = failed to pull and unpack image
failed to extract layer sha256:9ee7a25f1f619685e0c27cd1f08b34fd7a567f8f0fa789gf9aeb79c72169afa: hcsshim::ImportLayer failed in Win32: There is not enough space on the disk. (0x70): unknown
TrueNas Core 当前基准测试指标
我在日常的使用中, 如果是连续的文件,我其实感受不到磁盘性能的问题,一直都很好, 如果是小文件随机就非常的折磨。 这让我意识到自己还没有对磁盘进行基准测试 ,记录如下:TrueNAS 读取 和 写入的测试监控, 每次测试5mins,开始的时间是 9:55 , 所有磁盘都有写入的原因是 ,fio 在创建测试文件来测试读取。
ada0 是一个 sata ssd。ada1 和 ada2 是两个 hdd。
吞吐量:IOPS:
读取测试这个是符合预期的 read 的所有请求都来自于内存。
root@haydentruenas[/mnt/root_pool]# fio --name=seqread --rw=read --bs=1M --size=1G --numjobs=1 --runtime=300 --time_based --group_reporting
seqread: (g=0): rw=read, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=psync, iodepth=1
fio-3.28
Starting 1 process
seqread: Laying out IO file (1 file / 1024MiB)
Jobs: 1 (f=1): [R(1)][100.0%][r=806MiB/s][r=805 IOPS][eta 00m:00s]
seqread: (groupid=0, jobs=1): err= 0: pid=72054: Tue Jul 16 10:01:10 2024
read: IOPS=861, BW=861MiB/s (903MB/s)(252GiB/300001msec)
clat (usec): min=1059, max=28988, avg=1149.82, stdev=154.88
lat (usec): min=1060, max=28989, avg=1150.88, stdev=154.93
clat percentiles (usec):
| 1.00th=[ 1090], 5.00th=[ 1090], 10.00th=[ 1106], 20.00th=[ 1106],
| 30.00th=[ 1123], 40.00th=[ 1123], 50.00th=[ 1123], 60.00th=[ 1123],
| 70.00th=[ 1139], 80.00th=[ 1156], 90.00th=[ 1237], 95.00th=[ 1287],
| 99.00th=[ 1500], 99.50th=[ 1614], 99.90th=[ 2114], 99.95th=[ 2409],
| 99.99th=[ 6194]
bw ( KiB/s): min=507904, max=907772, per=100.00%, avg=882606.25, stdev=36668.31, samples=593
iops : min= 496, max= 886, avg=861.50, stdev=35.77, samples=593
lat (msec) : 2=99.87%, 4=0.12%, 10=0.01%, 20=0.01%, 50=0.01%
cpu : usr=1.58%, sys=98.14%, ctx=20974, majf=0, minf=257
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=258344,0,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
READ: bw=861MiB/s (903MB/s), 861MiB/s-861MiB/s (903MB/s-903MB/s), io=252GiB (271GB), run=300001-300001msec
写入测试写入的测试结果看起来没有那么美好,感觉是psync的原因, 没过内存数据直接写入的机械硬盘,看起来这个速度有点差, 这个盘 6Gbps 的总线, 能达到 83.3MiB/s, 感觉还是有点儿问题, 这个性能不足应该来自蜗牛星际的 IO 板子可能不太行。
root@haydentruenas[/mnt/root_pool]# fio --name=seqread --rw=write --bs=1M --size=1G --numjobs=1 --runtime=300 --time_based --group_reporting
seqread: (g=0): rw=write, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=psync, iodepth=1
fio-3.28
Starting 1 process
Jobs: 1 (f=1): [W(1)][100.0%][w=78.2MiB/s][w=78 IOPS][eta 00m:00s]
seqread: (groupid=0, jobs=1): err= 0: pid=72202: Tue Jul 16 10:09:24 2024
write: IOPS=83, BW=83.3MiB/s (87.4MB/s)(24.4GiB/300007msec); 0 zone resets
clat (usec): min=642, max=956978, avg=11914.63, stdev=7270.55
lat (usec): min=684, max=957053, avg=11987.96, stdev=7270.61
clat percentiles (usec):
| 1.00th=[ 766], 5.00th=[ 9765], 10.00th=[ 11076], 20.00th=[ 11338],
| 30.00th=[ 11469], 40.00th=[ 11469], 50.00th=[ 11600], 60.00th=[ 11863],
| 70.00th=[ 11994], 80.00th=[ 12256], 90.00th=[ 13042], 95.00th=[ 14222],
| 99.00th=[ 22938], 99.50th=[ 35390], 99.90th=[ 49546], 99.95th=[ 54264],
| 99.99th=[225444]
bw ( KiB/s): min= 7501, max=686786, per=100.00%, avg=85553.58, stdev=31496.12, samples=594
iops : min= 7, max= 670, avg=83.08, stdev=30.76, samples=594
lat (usec) : 750=0.93%, 1000=0.21%
lat (msec) : 2=0.84%, 4=0.51%, 10=2.88%, 20=93.54%, 50=1.03%
lat (msec) : 100=0.06%, 250=0.01%, 500=0.01%, 1000=0.01%
cpu : usr=0.71%, sys=7.19%, ctx=197395, majf=0, minf=0
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=0,25001,0,0 ...
TrueNas Scale 让 ZFS 占用更多内存作为 ARC
安装 TrueNas Scale 玩儿了一下, 劝退了有点。
TrueNAS Scale 作为 Linux Based 版本在使用内存上比较谨慎, ARC 并不会使用所有的内存, 这样的设计过于保守了。 内存当然是利用的越充分越好。
Config the ARC Memory to 75% Total Memory :
$ echo 2995556352 > /sys/module/zfs/parameters/zfs_arc_max
$ echo 268435456 > /sys/module/zfs/parameters/zfs_arc_sys_free
也可以使用一个这样的 shell 脚本来进行分析和配置。这个脚本会将 arc 的比例调整到 90% 的总内存。
#!/bin/sh
PATH="/bin:/sbin:/usr/bin:/usr/sbin:${PATH}"
export PATH
ARC_PCT="90"
ARC_BYTES=$(grep '^MemTotal' /proc/meminfo | awk -v pct=${ARC_PCT} '{printf "%d", $2 * 1024 * (pct / 100.0)}')
echo ${ARC_BYTES} > /sys/module/zfs/parameters/zfs_arc_max
SYS_FREE_BYTES=$((8*1024*1024*1024))
echo ${SYS_FREE_BYTES} > /sys/module/zfs/parameters/zfs_arc_sys_free
在EC2实例每次启动的时候都运行Userdata
使用Cloud-init提供读取Userdata的功能。
需要在Userdata中添加一个 MIME 的头部, 覆盖默认的行为。
https://cloudinit.readthedocs.io/en/latest/topics/format.html#mime-multi-part-archivehttps://repost.aws/zh-Hans/knowledge-center/execute-user-data-ec2
具体需要添加的MIME 部分:
Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0
--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"
#cloud-config
cloud_final_modules:
- [scripts-user, always]
--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"
之后重新启动这个EC2 就可以了。
Troubleshooting Guide
首先可以的查看Userdata , 在控制台 或者 AWScli
查看实例内部日志 或者 Console的日志:/var/log/cloud-init.log/var/log/cloud-init-output.log
查看userdata 注入的脚本内容:/var/lib/cloud/instances/i-09e08d362af7fa401/scripts 在这个目录下。文件树 : [root@ip-172-31-50-3 i-09e08d362af7fa401]# tree
.
├── boot-finished
├── cloud-config.txt
├── datasource
├── handlers
├── obj.pkl
├── scripts # 这个
│ ├── part-001
│ └── part-002
├── sem
│ ├── config_amazonlinux_repo_https
│ ├── config_disk_setup
│ ├── config_keys_to_console
│ ├── config_locale
│ ├── config_mounts
│ ├── config_phone_home
│ ├── config_power_state_change
│ ├── config_resolv_conf
│ ├── config_rsyslog
│ ├── config_runcmd
│ ├── config_scripts_per_instance
│ ├── config_scripts_user
│ ├── config_set_hostname
│ ├── config_set_passwords
│ ├── config_ssh
│ ├── config_ssh_authkey_fingerprints
│ ├── config_timezone
│ ├── config_users_groups
│ ├── config_write_files
│ ├── config_write_metadata
│ ├── config_yum_add_repo
│ ├── config_yum_configure
│ └── consume_data
├── user-data.txt
├── user-data.txt.i
├── vendor-data.txt
└── vendor-data.txt.i
3 directories, 33 files
如果需要临时的改一些内容, 可以写在Userdata里面, 完成操作之后删除Userdata 就可以了。
Linux_Kubernetes常用debug命令
查看 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
正见——佛陀的证悟(三)诸法无我 (选摘)
所有这些不同的情绪及其结果,都来自于错误的理解,而这个误解来自一个源头,也就是所有无明的根源—-执着于自我。
自我只是另一个误解。当我们看着自己的身体(色)、感受(受)、想法(想)、行为(行)和意识(识)的时候,我们通常制造出一种自我的概念。人们受制约,把这种概念视为恒常而且真实的。
但是悉达多了悟到,不论是在身体里或外,都找不到一个独立存在的实体,足以被称为自我。如同火圈的视觉错幻一般,自我也是虚幻的。它是谬误的;基本上错误,而究竟上不存在。但是如同我们被火圈所迷惑一般,我们也全都被自我所迷惑了,执着于谬误的自我,是无明的荒谬行为。它不断地制造更多的无明,导致了各种痛苦和失望。
无明单纯的就是不了解事实,或对事实了解不正确,或认识得不完整。所有这些形式的无明,都导致误解和误判,高估和低估。假设你正在寻找一个朋友,忽然看到他在远方的田野中。一走近,却发现你误把一个稻草人当做是他了。你一定会感到失望。这并非有个恶作剧的稻草人或你的朋友试图偷偷摸摸误导你,而是你自己的无明背叛了你。任何源自无明所做的行为,都是冒险。我们在不了解或不完全了解的情况下行动,就不会有信心。我们根本的不安全感因此而生起。创造出所有这些有名或无名、已知或未知的各种情绪。
悉达多了悟到自我并非独立存在、自我只不过是一个标签、因而执着于自我就是无明,这可能是人类历史上最大的发现。然而,虽然自我这个标签或许毫无根据,要摧毁它却不是一个简单的任务。执着于这个称作自我的标签,是所有的概念中最难以破除的。
魔罗只不过是悉达多的我执。故事中,描述魔罗是个英俊威武、无役不克的战士,这个比喻相当适切。自我,如同魔罗一般,威力强大且贪得无厌、自我中心且虚伪欺诈、贪求众人目光、机敏伶俐且爱慕虚荣。我们很难记住,自我如同火圈的幻相一般,是和合而成、不独立存在而且善于改变。
骄慢和自怜息息相关。我执纯粹是一种自我纵容,认为自己的生命比其他人的都更艰难更悲哀。当自我发展出自怜的时候,便让其它人生起悲悯的空间消失了。
虽然我们不认为自己这么绝望,而且相信自己是受过教育、正常、清醒的,但是当我们看见及感受一切都是真实存在时,我们的行为就如同那位沙漠中的迷失者。我们急切地想要找到真实的伴侣关系、安全感、表扬、成功,或只是安详宁静。我们甚至能抓到与欲望相似的东西。但就象那位迷失者,当我们依赖外在的实体性时,终究会失望。事物并不如其所显现—–它们是无常的,而且不完全在我们的掌控之中。
如果我们象悉达多一样确实地去分析,就会发现诸如形体、时间、空间、方向、大小等附加的标签,都很容易被解构。悉达多了悟到,甚至自我都只存在于相对的层次,恰如海市蜃楼一般。他的体悟,终止了期待、失望与痛苦的循环。在证悟的时刻,他自忖,我已找到了一条深奥、安详、非极端、清晰、满愿又有如甘露一般之道。然而,如果我想表达它,如果我想教给他人,没有人有能力听闻了解。因此我将留在林中,安住于此祥和状态之中。
然而,悉达多并非不理性,他只是明确地指出一般的、理性的思惟是有限的。我们不能,或不愿超越我们自己的舒适区去了解。用昨日、今日、明日这种线性的概念来操作,比如说“时间是相对的”,来得实用得多。我们没有被设定成这么想的:我能不改变大小或形状而进入那牦牛角。我们不能破除大和小的概念;相反的,我们一直被世代传下来的安全而狭隘的观点所局限。然而,当这些观点被审视时,却都站不住脚。举例来说,这个世界如此依赖的线性时间观念,无法说明时间没有真正的起始也没有终止的事实。
因此当我们听到一个人不改变尺寸,就可容入牦牛角中时,我们没有太多选择—–我们可以很“理性”,认为这根本不可能而驳斥它;或者我们引用某种对法术的神秘信仰或盲目崇拜而说,当然,密勒日巴是多么伟大的瑜珈行者,当然他能这么做,甚至还不只是这些呢。这两种见解都是扭曲的,因为否认是一种低估,而盲信则是一种高估。
一条河,水在流,永远在变,然而我们仍然称它为河流。如果一年之后我们再度造访,会认为它是同一条河。但它是如何相同的呢?如果我们单独挑出一个面向或特性,这相同性就不成立了。水不同了,地球在银河中转动的位置也不同了,树叶已落,新叶又长出来了—-剩下的只是一个相似于我们上次见到的河流表象而已。以“表象”作为“真实”的基础是相当不可靠的。经由简单的分析,就能显示出我们一般对所谓真实的基础,都只是一些模糊的概括和假设。虽然悉达多也使用一般人定义“真实”时所用的字眼—-非想象的、确定的、不改变的、无条件的—-但他更精确地使用这些字眼,而非概括性的。在他的观点上,不改变必然意指在所有的方面都不改变,甚至经过彻底的分析后,仍然绝无例外。
悉达多发现,要确定某个东西真实存在的唯一办法,就是证明它独立存在,而且不需要诠释、不能造作或不会改变。对悉达多而言,我们日常生活上一切似乎能作用的机制,不论是身体的、情感的及概念的,都是由不稳固、不恒常的部分所聚合而成,因此它们随时都在改变。我们可以在惯常的世界中了解这个论点。举例来说,你可以说你在镜中反射的影像不是真实存在的,因为他需要依赖你站在镜子前面才行。类似的,事物要真实或独立地存在,就不能被制作或被创造的,因为这要依赖制造者。
许多对佛陀的教法不甚了解的人,认为佛教是病态的,他们认为佛教徒否定快乐,只想到痛苦。他们设想佛教徒排斥美丽及身体的享受,因为这些是诱惑;佛教徒应该是纯净而节制的。事实上,在悉达多的教法中,并不特别反对美丽和享乐甚于其它的任何概念--只要我们不认为它们是真实存在的,而迷失其中。
虽然悉达多证悟了空性,但空性并不是由他或任何人所制造的。空性不是悉达多获得天启的结果,也不是为了让人们快乐所发展出来的理论。不论悉达多开示与否,空性即是如此。我们甚至不能说它一直都是如此,因为它超越时间,而且不具形式。空性也不应被解释为存在的否定(也就是说,我们不能说这个相对的世界不存在),因为要否定某个事物,你就要先承认有某个东西可以被否定才行。空性也不会消除我们日常的经验。悉达多从来没说过有什么可以取代我们所觉受的更壮丽、更美好、更纯粹或更神圣的东西。他也不是虚无主义者,否定世间存在事物的显现与功能。
悉达多会同意这两种情况--当你醒着时,你不能飞;而当你睡着时,你能飞。这道理是在于因缘是否具足;要能飞翔的一个缘,是睡眠。当你没有它,你就不能飞,有了它,你就能飞。假设你梦见你能飞,而醒来后还继续相信你能飞,那就麻烦了。你会掉下来,而且会失望。悉达多说,即使在相对世界中醒着,我们还是在无明中沉睡,如同在他出走那夜的宫女一般。恰当的因缘聚合时,任何事情都可能出现。但当因缘消散,显现也就停止。
这也是为何在悉达多教法一千五百年后,一位叫帝洛巴的佛法继承者,对他的学生那洛巴说,不是显现(外相)困住了你,而是你对显现(外相)的执着困住了你。
如同环球小姐选美一样,在这个世界上,我们所做、所想的任何事物,都有是基于一个非常有限的共同逻辑系统。我们非常强调共识。如果大多数人同意某件事物是真实的,通常它就变成正当有效的。当我们看着一个小池塘,我们人类认为它只是个池塘,但对池里的鱼儿来说,这是它们的宇宙。如果我们采取民主的立场,那么水中族群一定会赢,历为它们比我们这些观池塘者为数多得多。多数决不见得永远都对。糟糕的大卖座影片可以赚得大量的利润,而一部独立制作的优秀影片却只有少数人观赏。而且由于我们依赖群体思考,这世界通常是被最短视而腐败的统治者所治理;民主制度只是诉诸于最小公约数而已。
然而了悟不必是致命的。我们不需要象井蛙一般,面对空性惊吓而亡。如果海蛙能够有稍微多点的慈悲心和善巧,也许它可以做一个更好的向导,井蛙也不至于吓死,也许它还会移居到海边也说不定。而我们也不需要有超自然的天赋才能了解空性。这和教育以及愿意观察事物所有的部分以及隐藏的因缘有关。有了这种洞见,我们就会象布景设计师或摄影助理在看电影。专业者能看见我们所看不见的东西。他们看见摄影机如何布置,以及其他观众们不知道的电影技巧,因此对他们而言,这幻相被拆解了。但专业者在看电影的时候,还是可以尽情享受。这就是悉达多超然的幽默。
悉达多没有一开始就用空性来惊吓大家,反而以一般的方式,诸如禅定以及行为规范--做正确的事、勿盗窃、勿妄言等来教导众多的弟子。根据弟子的本性,他定下了不同程度的出离及苦行,从削发到不食肉等等。对一开始无法听闻或了解空性的人,以及天性适合苦修的人而言,这些状似宗教性的严格道路很有效。
业(Karma)这个字几乎和佛教成了同义字。通常它被理解为一种道德系统的报应—-恶业与善业。然而,业只是一种因果的法则,不应该与道德或伦理混淆。
你也行会认为这是矛盾的。佛陀自我矛盾,说他不存在,一切皆是空性,然后他又教导了道德和救赎。然而这些方法是必要的,以免吓走那些尚未准备好,还不能被引介空性的人。他们用了这些方法,因而变得祥和,易于接受真正的教法,这就如同说那里是有一条蛇。然后把领带丢到窗外一般。这些无限的方法就是道路。然而,道路本身终究也需要被抛弃,如同你抵达彼岸时,就得抛弃舟一般。你抵达时必须要下船。在完全证悟的那一刻,你必须抛弃佛教。精神之路是一个暂时解答,它是在空性被了悟之前所使用的安慰剂。
如同在电影院里的孩童,我们被幻相掳获了。从这儿开始,衍生了我们的虚荣、野心和不安全感。我们爱上了自己创造的幻相,发展出对自己的外表、财富和成就过度的骄慢。好比戴了面具,却骄傲地认为面具是真实的你。
了悟空性的悉达多,对菩提树下的忘忧草或宫殿里的丝绸坐垫没有好恶分别。金线织成的坐垫价值较高,完全是由人类的野心和欲望造作而来的。事实上,山中的隐士也许会觉得忘忧草比较柔软而干净,而且最大的好外是坐坏了也不需要担心。你不需要对它喷药,以免猫用爪子去抓它。宫廷生活充满了这类的“珍品”,需要相当多的维修保养。悉达多是属于比较喜欢草垫的人,因此他不需要常常回家去补充什么东西。
我们人类认为心胸宽广是一种美德。要扩展心胸,重要的是不要安于令我们舒适或习惯的东西。如果我们有勇气超越世俗,不被惯常逻辑的界线所限制,就能得到利益。如果我们能超越界线,就能了解空性是如此可笑地单纯。密勒日巴躲进牦牛角不会比某个人戴上手套还令你讶异。我们所要挑战的,是对惯常逻辑、文法、字母、数学公式的执着。如果能记得这些习惯的和合本性,我们就能断除它们。它们不是不能破除的,所需要的只是一个条件完全正确、资讯适时到位的情况,你可能突然发现所有依赖的工具都不是那么坚实,它们有弹性、可弯曲。你的观点会改变。