跳转至

devops

用 Kubernetes 部署无状态服务

背景

最近需要部署一个用来跑编译的服务,服务从 MQ 取任务,编译完以后提交任务。最初的做法是包装成 docker,然后用 docker-compose 来 scale up。但既然有 k8s 这么好的工具,就试着学习了一下,踩了很多坑,总结了一些需要用到的命令。

搭建 Docker Registry

首先搭建一个本地的 Docker Repository,首先设置密码:

$ mkdir auth
$ htpasswd user pass > auth/passwd

然后运行 registry:

$ docker run -d -p 5000:5000 \
        --restart=always \
        --name registry \
        -v "$(pwd)/registry":/var/lib/registry \
        -v "$(pwd)/auth":/auth \
        -e "REGISTRY_AUTH=htpasswd" \
        -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
        -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
        registry:2

简单起见没有配 tls。然后吧本地的 image push 上去:

$ docker tag $image localhost:5000/$image
$ docker push localhost:5000/$image

这样就可以了。

搭建 k8s 环境

考虑到只用了单个物理机,所以采用的是 minikube。首先下载 minikube,下载方法略去。

接着新建 minikube 虚拟机:

$ minikube start --registry-mirror=https://registry.docker-cn.com --image-mirror-country=cn --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers --vm-driver=kvm2 --insecure-registry="0.0.0.0/0" --disk-size=50GB --cpus 128 --memory 131072

这里的 0.0.0.0/0 可以缩小,磁盘、CPU 和内存需要在这里就设好,之后不能改,要改只能重新开个虚拟机,不过这个过程也挺快的。

然后初始化一些组件(metrics server 和 kubernetes dashboard):

$ minikube addons enable metrics-server
$ minikube dashboard

如果要访问 dashboard 的话,可以用上面命令输出的链接,或者用 kubectl proxy 然后打开 http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ (注意 http 还是 https)。

如果问到 Access Token,可以用以下 alias 获得(fish/macOS):

$ alias kubedashboard="kubectl -n kubernetes-dashboard describe secret (kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print \$1}') | tail -n1 | awk '{print \$2}' | pbcopy"

接着,配置一下 docker registry 的密钥:

$ kubectl create secret generic regcred --from-file=.dockerconfigjson=/path/to/config.json  --type=kubernetes.io/dockerconfigjson

然后,在 Pod/Deployment 里面设定镜像:

containers:
  - name: name
    image: IP:5000/image
imagePullSecrets:
  - name: regcred

然后部署即可。

部署水平自动伸缩(HPA)

这一步配置的是自带的 HPA 功能,需要上述的 metrics-server 打开,并且在 Pod/Deployment 里面写明 resources.requests.cpu:

- name: name
  resources:
    requests:
      cpu: "xxx"

然后创建 HPA 即可:

$ kubectl autoscale deployment $deployment --cpu-percent=50 --min=1 --max=10

通过压测,可以看到自动伸缩的记录:

$ kubectl describe hpa
Normal  SuccessfulRescale  22s   horizontal-pod-autoscaler  New size: 4; reason: cpu resource utilization (percentage of request) above target
Normal  SuccessfulRescale  6s     horizontal-pod-autoscaler  New size: 1; reason: All metrics below target

参考:Kubernetes 官方文档

用 jailkit 限制用户仅 scp

最近需要用 scp 部署到生产机器,但又不想出现安全问题,所以用了 jailkit 的方法。首先是创建单独的用户,然后生成 ssh key 来认证,不再赘述。此时是可以 scp 了,但用户依然可以获得 shell,不够安全。

然后找到了下面参考链接,大概摘录一下所需要的命令和配置:

mkdir /path/to/jail
chown root:root /path/to/jail
chmod 701 /path/to/jail
jk_init -j /path/to/jail scp sftp jk_lsh
jk_jailuser -m -j /path/to/jail jailed_user
vim /path/to/jail/etc/jailkit/jk_lsh.ini
# Add following lines
[jailed_user]
paths = /usr/bin, /usr/lib
exectuables = /usr/bin/scp

之后可以发现该用户的 shell 已经更改 jk_chrootsh,并且只能用 scp。

参考:https://blog.tinned-software.net/restrict-linux-user-to-scp-to-his-home-directory/

为 Cisco WLC 配置 Telegraf

最近想到可以给 Cisco WLC 也配置一下监控,查了一下,果然有一些方法。大概研究了一下,找到了方法:

把 https://github.com/haad/net-snmp/tree/master/mibs 和 https://github.com/zampat/neteye4/tree/master/monitoring/monitoring-plugins/wireless/cisco/mibs 目录下的所有 .txt 文件放到 /usr/share/snmp/mibs 目录下。

然后把 https://github.com/zampat/neteye4/blob/master/monitoring/monitoring-plugins/wireless/cisco/telegraf.conf 下面 snmp 的配置复制到 telegraf 配置中,然后修改一下 IP 地址。

确保 Cisco WLC 的 SNMP 的 Public Community 已经配置好,然后就可以拿到数据了。

目前可以拿到 WLC 自身的一些运行˙状态信息、AP 的信息、SSID 的信息和 Client 的信息,基本满足了我们的需求。

参考:https://www.neteye-blog.com/2019/08/monitoring-a-cisco-wireless-controller/

用 htpdate 替代 ntpdate 实现时间同步

最近用 ntpdate 的时候遇到了一些麻烦,时间同步总是遇到各种问题。后来搜了搜,发现了一个解决方案:htpdate,它通过 HTTP 头里的 Date 字段获取时间,虽然没有 ntp 那么精确,但是大多时候都够用。

用法见 htpdate(8)

Nginx 反代到 HTTPS 上游

这次遇到一个需求,要反代到不在内网的地址,为了保证安全,还是得上 HTTPS,所以尝试了一下怎么给 upstream 配置自签名 HTTPS 证书的验证。

upstream subpath {
    server 4.3.2.1:4321;
}

server {
    listen 443 ssl;
    server_name test.example.com;

    location /abc {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_ssl_trusted_certificate /path/to/self_signed_cert.crt;
        proxy_ssl_name 1.2.3.4; // to override server name checking
        proxy_ssl_verify on;
        proxy_ssl_depth 2;
        proxy_ssl_reuse on;
        proxy_pass https://subpath;
    }
}

可以用 openssl 获得自签名的 cert :

echo | openssl s_client -showcerts -connect 4.3.2.1:4321 2>/dev/null | \
                              openssl x509 -text > /path/to/self_signed_cert.crt

ref: https://stackoverflow.com/questions/7885785/using-openssl-to-get-the-certificate-from-a-server

在古老的 OS 上运行一个干净的新的环境

由于某些课程的原因,需要在一个 CentOS 7 上跑一些编译和运行代码。看到这么古老的软件,我心想不行,肯定要找新一些的软件来用。首先想到的是 tmux,于是按照网上的脚本 很快装了一个 tmux 2.8 版本,果然好了很多。但是常用的很多软件依然是个问题。试了一下最近比较新的 code-server,因为 ABI 问题跑不起来。

于是开始想玩骚操作。首先想到的是 Gentoo Prefix,不过既然是别人的机器,还是算了。又找了 fakeroot 配合 alpine rootfs 的方案,但编译不过,估计是内核版本问题。又试了一下 fakechroot,但它需要配合 fakeroot 使用,这就凉了。

然后又找了一些替代方案。一是 uchroot,但由于 CMake 版本太老也编译不过。最后发现了 PRoot ,直接提供 prebuilt 然后很容易就可以跑起来:

$ ./proot -b /proc -b /dev -r $CHROOT /bin/busybox sh

于是就进到了 alpine 的 rootfs 中,下载地址。进去以后发现没有编辑器,于是出来把 apk 的源改了,加了 resolv.conf,就成功地安装了很多很新的软件了。

用 MuSSH 快速对多台机器进行软件包升级

Debian Stretch 9.5 刚刚更新,自己手上有不少 stretch 的机器,于是顺手把他们都升级了。不过,这个过程比较繁琐,于是我采用了 MuSSH 的方法,让这个效率可以提高,即自动同时 SSH 到多台机器上进行更新。

首先编写 hostlist 文件,一行一个地址,分别对应每台机器。

然后采用 MuSSH 对每台机器执行同样的命令

$ mussh -H hostlist -c 'apt update && apt upgrade -y'

此时要求,ssh 上去以后有相应的权限。这个有许多方法,不再赘述。然后就可以看到一台台机器升级,打上安全补丁,爽啊。

在 Lemote Yeeloong 上安装 Debian jessie

参考网站:

gNewSense To MIPS Run a TFTP server on macOS Debian on Yeeloong Debian MIPS port wiki Debian MIPS port

首先,进入设备的 PMON:

Press Del to enter PMON

然后,下载 Debian Jessie 的 netboot 文件:

$ wget https://mirrors.tuna.tsinghua.edu.cn/debian/dists/jessie/main/installer-mipsel/current/images/loongson-2f/netboot/vmlinux-3.16.0-6-loongson-2f
$ wget https://mirrors.tuna.tsinghua.edu.cn/debian/dists/jessie/main/installer-mipsel/current/images/loongson-2f/netboot/initrd.gz

以 macOS 为例,起一个 tftp 服务器以供远程下载:

# ln -s these files to /private/tftpboot:
# initrd.gz
# vmlinux-4.16.0-6-loongson-2f
$ sudo launchctl load -F /System/Library/LaunchDaemons/tftp.plist
# set addr manually to 192.168.2.1

回到 PMON,配置远程启动:

> ifaddr rtl0 192.168.2.2
> load tftp://192.168.2.1/vmlinux-3.16.0-6-loongson-2f
> initrd tftp://192.168.2.1/initrd.gz
> g

之后就是熟悉的 Debian Installer 界面。起来之后,就可以顺手把 tftp 服务器关了:

$ sudo launchctl unload -F /System/Library/LaunchDaemons/tftp.plist

实测滚到 stretch 会挂。因为 stretch 虽然也有 mipsel 架构,但是它的 revision 与 Loongson-2f 不大一样,会到处出现 SIGILL 的问题,不可用。靠 jessie 和 jessie-backports 已经有不少的软件可以使用了。

通过 systemd-run 直接在容器中执行命令

之前使用 systemd-nspawn 开了容器,然后通过 machinectl shell 进去,想要起一个服务然后丢到后台继续执行,但是发现离开这个 session 后这个进程总是会被杀掉,于是找了 systemd-run 的方案,即:

systemd-run --machine machine_name_here absolute_path_to_executable args_here

这样可以直接在容器中跑服务,而且用这个命令输出的临时 server 名称,还可以看到日志:

journalctl --machine machine_name_here -u unit_name_above

在 Nginx 将某个子路径反代

现在遇到这么一个需求,访问根下面是提供一个服务,访问某个子路径(/abc),则需要提供另一个服务。这两个服务处于不同的机器上,我们现在通过反代把他们合在一起。在配置这个的时候,遇到了一些问题,最后得以解决。

upstream root {
    server 1.2.3.4:1234;
}
upstream subpath {
    server 4.3.2.1:4321;
}

server {
    listen 443 ssl;
    server_name test.example.com;

    # the last slash is useful, see below
    location /abc/ {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        # the last slash is useful too, see below
        proxy_pass http://subpath/;
    }

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://root;
    }
}

由于并不想 subpath 他看到路径中 /abc/ 这一层,导致路径和原来在根下不同,通过这样配置以后,特别是两个末尾的斜杠,可以让 nginx 把 GET /abc/index.html 改写为 GET /index.html,这样我们就可以减少许多配置。当然,我们还是需要修改一下配置,现在是 host 在一个新的域名的一个新的子路径下,这主要是为了在返回的页面中,连接写的是正确的。

在 VMware ESXi 上部署 vCSA 实践

首先获取 vCSA 的 ISO 镜像,挂载到 Linux 下(如 /mnt),然后找到 /mnt/vcsa-cli-installer/templates/install 下的 embedded_vCSA_on_ESXi.json,复制到其它目录并且修改必要的字段,第一个 password 为 ESXi 的登录密码,一会在安装的过程中再输入。下面有个 deployment_option,根据你的集群大小来选择,我则是用的 small。下面配置这台机器的 IP 地址,用内网地址即可。下面的 system_name 如果要写 fqdn,记得要让这个域名可以解析到正确的地址,不然会安装失败,我因此重装了一次。下面的密码都可以留空,在命令行中输入即可。SSO 为 vSphere Client 登录时用的密码和域名,默认用户名为 Administrator@domain_name (默认的话,则是 Administrator@vsphere.local) 这个用户名在安装结束的时候也会提示。下面的 CEIP 我选择关闭,设置为 false。

接下来进行安装。

$ /mnt/vcsa-cli-installer/lin64/vcsa-deploy install /path/to/embedded_vCSA_on_ESXi.json --accept-eula

一路输入密码,等待安装完毕即可。然后通过 443 端口进入 vSphere Client, 通过 5480 端口访问 vCSA 的管理页面。两个的密码可以不一样。

2018-05-21 Update: 想要设置 VMKernel 的 IPv6 网关的话,ESXi 中没找到配置的地方,但是在 vSphere Client 中可以进行相关配置。

在 macOS 上试用 Gentoo/Prefix

前几天参加了许朋程主讲的 Tunight,对 Gentoo 有了一定的了解,不过看到如此复杂的安装过程和长久的编译时间,又看看我的 CPU,只能望而却步了。不过,有 Gentoo/Prefix 这个工具,使得我们可以在其它的操作系统(如 macOS,Solaris 等)上在一个 $EPREFIX 下跑 Portage,也就是把 Portage 运行在别的操作系统,当作一个包管理器,并且可以和别的操作系统并存。

首先还是祭出官网:Project:Prefix

首先设定好环境变量 $EPREFIX ,之后所有的东西都会安装到这个目录下,把 bootstrap-prefix.sh 下载到 $EPREFIX ,然后 ./bootstrap-prefix.sh ,会进行一系列的问题,一一回答即可。建议在运行前设置好 GENTOO_MIRRORS=http://mirrors.tuna.tsinghua.edu.cn/gentoo 由于 TUNA 没有对 gentoo_prefix 做镜像,只能把 distfiles 切换到 TUNA 的镜像上。

然后。。。

stage1...

stage2..

stage3.

emerge -e @world BOOM

经过 n 次跑挂以后,终于搞完了 stage3,然后 SHELL=bash ./bootstrap-prefix.sh $EPREFIX startscript 生成 startprefix ,在外面的 SHELL 中向切进来的时候运行这个即可。

然后就可以使用Gentoo/Prefix了。注意!此时的 $PATH 仅限于 $EPREFIX 下几个目录和 /usr/bin /bin 所以很多东西都会出问题(Emacs, Vim, Fish etc)。小心不要把自己的目录什么的搞挂了。

然后就可以假装试用 Gentoo 了!

哈哈哈哈哈哈哈

死于编译 libgcrypt 和 llvm。