将 k8s rook ceph 集群迁移到 cephadm

背景 前段时间用 rook 搭建了一个 k8s 内部的 ceph 集群,但是使用过程中遇到了一些稳定性问题,所以想要用 cephadm 重建一个 ceph 集群。 重建过程 重建的时候,我首先用 cephadm 搭建了一个 ceph 集群,再把原来的 MON 数据导入,再恢复各个 OSD。理论上,可能有更优雅的办法,但我还是慢慢通过比较复杂的办法解决了。 cephadm 搭建 ceph 集群 首先,配置 TUNA 源,在各个节点上安装 docker-ce 和 cephadm。接着,在主节点上 bootstrap: cephadm bootstrap --mon-ip HOST1_IP 此时,在主节点上会运行最基础的 ceph 集群,不过此时还没有任何数据。寻找 ceph 分区,会发现因为 FSID 不匹配而无法导入。所以,首先要恢复 MON 数据。 参考文档:cephadm install。 恢复 MON 数据 首先,关掉 rook ceph 集群,找到留存下来的 MON 数据目录,默认路径是 /var/lib/rook 下的 mon-[a-z] 目录,找到最新的一个即可。我把目录下的路径覆盖到 cephadm 生成的 MON 目录下,然后跑起来,发现有几个问题: cephadm 生成的 /etc/ceph/ceph.client.admin.keyring 与 MON 中保存的 auth 信息不匹配,导致无法访问 FSID 不一致,而 cephadm 会将各个设置目录放到 /var/lib/ceph/$FSID 下 第一个问题的解决办法就是临时用 MON 目录下的 keyring 进行认证,再创建一个新的 client.

Read More

C++ 11 的 ABI 问题

背景 有同学遇到这样的一个问题,代码中链接了一个第三方的动态库,在链接的时候出现了不一致的问题,比如有一个函数签名如下: void foobar(std::string s) {} 使用 GCC 11.1.0 编译上面的代码,可以发现它需要的符号是 _Z6foobarNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE,但是第三方库里面却是 _Z6foobarSs,因此找不到对应的符号,链接失败。 问题 经过一番研究,发现 Ss 在 Itanium ABI 中表示的是缩写: In addition, the following catalog of abbreviations of the form "Sx" are used: <substitution> ::= St # ::std:: <substitution> ::= Sa # ::std::allocator <substitution> ::= Sb # ::std::basic_string <substitution> ::= Ss # ::std::basic_string < char, ::std::char_traits<char>, ::std::allocator<char> > <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> > <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> > <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> > 这看起来很正常,_Z6foobarSs 表示的是 foobar(std::basic_string<char, std::char_traits<char>, std::allocator<char> >),但是 GCC 11.

Read More

硬盘相关的概念

ATA ATA 定义了发送给硬盘的命令,标准定义了命令: ech IDENTIFY DEVICE: 获取设备信息 25h READ DMA EXT: 读取扇区 35h WRITE DMA EXT: 写入扇区 ATA 同时也是接口,图片如下。ATA 前身是 IDE,现在 ATA 叫做 PATA。 AHCI AHCI 可以简单理解为 PCIe <-> SATA 的转换器。AHCI 暴露为一个 PCIe 设备: $ lspci -vv 00:1f.2 SATA controller: Intel Corporation C600/X79 series chipset 6-Port SATA AHCI Controller (rev 05) Kernel modules: ahci 处理器通过 IO port/MMIO 访问 AHCI,然后 AHCI HBA 连接到 SATA 设备。 SATA SATA 一般说的是接口。它一般分为两个部分,数据和电源。数据部分只有 7 个 pin,三个 GND 和两对差分线(A+A- B+B-),图片如下:

Read More

在 ESXi 中用 PERCCli 换 RAID 中的盘

背景 最近有一台机器的盘出现了报警,需要换掉,然后重建 RAID5 阵列。iDRAC 出现报错: Disk 2 in Backplane 1 of Integrated RAID Controller 1 is not functioning correctly. Virtual Disk 1 on Integrated RAID Controller 1 has become degraded. Error occurred on Disk2 in Backplane 1 of Integrated RAID Controller 1 : (Error 2) 安装 PERCCli 首先,因为系统是 VMware ESXi 6.7,所以在DELL 官网下载对应的文件。按照里面的 README 安装 vib: esxcli software vib install -v /vmware-perccli-007.1420.vib 如果要升级系统,需要先卸载 vib:esxcli software vib remove -n vmware-perccli,因为升级的时候会发现缺少新版系统的 perccli,建议先卸载,升级后再安装新的。

Read More

用 fluentd 收集 k8s 中容器的日志

背景 在维护一个 k8s 集群的时候,一个很常见的需求就是把日志持久化存下来,一方面是方便日后回溯,一方面也是聚合 replicate 出来的同一个服务的日志。 在我目前的需求下,只需要把日志持久下来,还不需要做额外的分析。所以我并没有部署类似 ElasticSearch 的服务来对日志进行索引。 实现 实现主要参考官方的仓库:https://github.com/fluent/fluentd-kubernetes-daemonset。它把一些常用的插件打包到 docker 镜像中,然后提供了一些默认的设置,比如获取 k8s 日志和 pod 日志等等。为了达到我的需求,我希望: 每个结点上有一个 fluentd 收集日志,forward 到单独的 log server 上的 fluentd log server 上的 fluentd 把收到的日志保存到文件 由于 log server 不由 k8s 管理,所以按照官网的方式手动安装: $ curl -L https://toolbelt.treasuredata.com/sh/install-debian-buster-td-agent4.sh | sh 然后,编辑配置 /etc/td-agent/td-agent.conf: <source> @type forward @id input_forward bind x.x.x.x </source> <match **> @type file path /var/log/fluentd/k8s compress gzip <buffer> timekey 1d timekey_use_utc true timekey_wait 10m </buffer> </match> 分别设置输入:监听 fluentd forward 协议;输出:设置输出文件,和 buffer 配置。如有需要,可以加鉴权。

Read More

静态编译 ipmitool

为了在 ESXi 上运行 ipmitool,需要静态编译 ipmitool。网上已经有一些解决方案: https://github.com/ryanbarrie/ESXI-ipmitool https://github.com/hobbsh/static-ipmitool https://github.com/ewenmcneill/docker-build-static-ipmitool 我稍微修改了一下,用来编译最新 ipmitool: #!/bin/bash set -x export VERSION=1.8.18 rm -rf ipmitool_$VERSION curl -L -o ipmitool_$VERSION.tar.bz2 http://deb.debian.org/debian/pool/main/i/ipmitool/ipmitool_$VERSION.orig.tar.bz2 tar xvf ipmitool_$VERSION.tar.bz2 cd ipmitool-$VERSION CC=gcc CFLAGS=-m64 LDFLAGS=-static ./configure make -j24 cd src ../libtool --silent --tag=CC --mode=link gcc -m64 -fno-strict-aliasing -Wreturn-type -all-static -o ipmitool.static ipmitool.o ipmishell.o ../lib/libipmitool.la plugins/libintf.la file $PWD/ipmitool.static 复制下来,编译完成后 scp 到 esxi 中即可使用。

Read More

通过 ipmitool 配置 iLO 4 管理端口

ipmitool 自带了对 iDRAC 的支持,可以通过 ipmitool delloem 设置 iDRAC 的管理端口。但是对 iLO 的支持并没有实现。研究了一番,找到了通过 raw command 配置 iLO 4 管理端口的方法。 这篇文章 讲述了 ipmitool lan 命令实际会发送的命令: 读取配置: $ ipmitool raw 0x0c 0x02 CHANNEL KEY SET BLOCK 一般来说 SET 和 BLOCK 都是 0。KEY 的常见取值: 3: IP 地址 4: IP 地址来源 5: MAC 地址 6: 子网掩码 12: 默认网关 返回的数据中,第一个字节忽略,剩下的就是数据了。 写入配置: $ ipmitool raw 0x0c 0x01 CHANNEL KEY DATA... 知道如何读取配置后,接下来就是找到 iLO 4 配置 NIC 的地方了。一番搜索,找到了 HPE iLO IPMI User Guide。在第 101 页,可以找到一个用于配置 iLO NIC 选择的设置:

Read More

ESXi 网络配置

用过 ESXi 的大家都知道,它网页版对网络的配置功能有限,特别是 IPv6 的部分,有的事情无法实现。更好的办法是 SSH 到 ESXi 上直接用命令行进行配置。 可能会用到的一些命令: esxcfg-vmknic: 用来给 vmkernel 配置地址 esxcfg-route: 设置系统路由表 esxcli: 大杂烩,很多功能都在里面 tcpdump-uw:魔改版 tcpdump 一些例子: 设置 IPv6 默认路由: [root@esxi:~]esxcfg-route -f V6 -a default $IPV6 删除 vmkernel 的 IPv6 地址: [root@esxi:~]esxcli network ip interface ipv6 address remove -i $VMKERNEL -I $IPV6/$PREFIX 参考:https://kb.vmware.com/s/article/1002662

Read More

Linksys E8450 OpenWRT 配置 w/ 802.11ax

背景 之前用的 newifi 路由器(Lenovo y1s)无线网总是出问题,于是换了一个新的支持 802.11ax 的路由器 Linksys E8450,目前在 openwrt snapshot 支持。Openwrt 的支持页面:Linksys E8450。 过程 按照支持页面,下载固件: $ wget https://downloads.openwrt.org/snapshots/targets/mediatek/mt7622/openwrt-mediatek-mt7622-linksys_e8450-squashfs-sysupgrade.bin 然后访问固件升级页面:http://192.168.1.1/config-admin-firmware.html#firmware,选择下载的 bin 文件。点击 “开始升级”,然后等待。一段时间后,ssh 到路由器: $ ssh root@192.168.1.1 The authenticity of host '192.168.1.1 (192.168.1.1)' can't be established. ED25519 key fingerprint is SHA256:REDACTED. No matching host key fingerprint found in DNS. This key is not known by any other names Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '192.

Read More

用 gitlab ci 构建并部署应用到 k8s

背景 在 k8s 集群中部署了 gitlab-runner,并且希望在 gitlab ci 构建完成后,把新的 docker image push 到 private repo,然后更新应用。 参考文档:Gitlab CI 与 Kubernetes 的结合,Using Docker to build Docker images。 在 gitlab ci 中构建 docker 镜像 这一步需要 DinD 来实现在容器中构建容器。为了达到这个目的,首先要在 gitlab-runner 的配置中添加一个 volume 来共享 DinD 的证书路径: gitlabUrl: REDACTED rbac: create: true runnerRegistrationToken: REDACTED runners: config: |[[runners]] [runners.kubernetes] image = "ubuntu:20.04" privileged = true [[runners.kubernetes.volumes.empty_dir]] name = "docker-certs" mount_path = "/certs/client" medium = "Memory" privileged: true 注意两点:1.

Read More