离线安装k3s(Air Gap Install)
准备离线文件
从https://github.com/k3s-io/k3s/releases
下载以下文件:
* k3s-airgap-images-amd64.tar.zst
* k3s
从https://rancher-mirror.rancher.cn/k3s/k3s-install.sh
下载k3s-install.sh文件。
离线安装(Ubuntu 22.04)
将k3s-airgap-images-amd64.tar.zst文件上传到服务器的
/var/lib/rancher/k3s/agent/images/
目录下1
2sudo mkdir -p /var/lib/rancher/k3s/agent/images/
sudo cp k3s-airgap-images-amd64.tar.zst /var/lib/rancher/k3s/agent/images/将k3s文件上传到服务器的
/usr/local/bin/
目录下1
2sudo cp k3s /usr/local/bin/
sudo chmod +x /usr/local/bin/k3s将k3s-install.sh文件上传到服务器
执行安装脚本
1
2
3
4
5chmod +x k3s-install.sh
sudo INSTALL_K3S_SKIP_DOWNLOAD=true \
INSTALL_K3S_EXEC='server --token=23f0fba79fc84fd5962279908c86d05e --cluster-init' \
./k3s-install.sh
挂载NAS
在阿里云控制台查看具体操作
helm安装(ubuntu 22.04)
1 | cp /etc/rancher/k3s/k3s.yaml ~/.kube/config |
使用Lens访问
在https://k8slens.dev/
下载Lens安装包,支持windows,需要通过XShell的隧道来打通网络。
使用Docker下载镜像再导入到k8s
下载
1 | docker save registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.9.2 -o kube-state-metrics-v2.9.2.tar |
导入
1 | k3s ctr image import kube-state-metrics-v2.9.2.tar |
注意:如果镜像的下载策略(imagePullPolicy
)是Always
,则始终会重新下载镜像,所以要使用导入的镜像,需要将镜像下载策略改为IfNotPresent
kube-prometheus
1 | kubectl apply --server-side -f manifests/setup |
安装Docker(Ubuntu)
1 | sudo apt install docker.io |
配置镜像加速(阿里云)
1 | sudo mkdir -p /etc/docker |
rancher(弃用)
Rancher安装后默认开启了一个内置的k3s集群,但是无法增加自建的k8s集群?或许只用k3s才是最简单的方式?毕竟Rancher带来了更多的复杂性和不可控性。
持久化存储(longhorn)
1 | wget https://raw.githubusercontent.com/longhorn/longhorn/v1.5.1/deploy/longhorn.yaml |
TODO: 部署Docker私有镜像服务,使用阿里云NAS存储镜像,然后让k3s使用私有镜像仓库。
https://zhuanlan.zhihu.com/p/78543733
https://blog.csdn.net/kidom1412/article/details/108128859
自建容器镜像仓库虽然存在单点瓶颈,还是比从文件中手动加载要,毕竟可以由k8s自动处理,新加入的节点也可以自动拉取镜像。
Docker 运维记录
Fix No chain/target/match by that name
最近在Alibaba Cloud Linux 3
上使用audo apt update
进行系统升级后,某个Docker容器无法重启,错误如下:
1 | Error response from daemon: Cannot restart container some-app: driver failed programming external connectivity on endpoint some-app (88301987d72d07ba99c1630461e1ade9d1fb53879b1d6f94fc8571ac7db7e2a6): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 9015 -j DNAT --to-destination 172.17.0.3:9015 ! -i docker0: iptables: No chain/target/match by that name. |
首先排除了iptables的原因,因为我们在做容器化部署的服务器上,都禁用了iptables。
然后怀疑是系统更新的时候,影响到了Docker容器的某些配置,导致容器无法重启。但是重建容器后,还是无法重启,报一样的错误。
最后搜索了一下,找到了解决办法:
参考:docker启动容器报错(iptables failed)
重启docker服务即可:
1 | systemctl restart docker |
Docker容器的健康检测和自动重启
容器的健康检测
如果在Dockerfile或者docker run命令里进行了健康检测,容器启动后查看状态会多出一个信息:healthy或者unhealthy。
1 | # docker ps |
在Dockerfile里配置健康检测
1 | HEALTHCHECK --interval=10s --timeout=2s --start-period=30s --retries=3 CMD curl --silent --fail http://localhost:7015/actuator/health || exit 1 |
在容器启动时指定健康检测参数
1 | docker run ... |
自动重启unhealthy的容器
参考Github项目: Autoheal
大致是说本来docker run
有一个issue,或者说应该有那么一个功能,参数--exit-on-unhealthy
,默认值true
,在容器unhealthy时就退出。再配合--restart=on-failure
,来实现容器的自动重启。在exit-on-unhealthy
没实现之前,就用这个Autoheal来实现这个功能。
1 | docker run -d \ |
- AUTOHEAL_CONTAINER_LABEL的默认值是autoheal,表示Autoheal会监视带有标签
--label autoheal=true
的容器。 - 设置AUTOHEAL_CONTAINER_LABEL=all则是监视所有正在运行的容器。
- 也可以自定义AUTOHEAL_CONTAINER_LABEL的值,比如
AUTOHEAL_CONTAINER_LABEL=myapp
,这会监视所有带myapp=true
标签的容器。(说实话,官方的这句Set ENV AUTOHEAL_CONTAINER_LABEL to existing label name that has the value true.
,最初让我懵了一下。)
探索容器化部署Spring Boot应用
本文主要探索容器化部署Spring Boot应用的一些方案,包括Docker Compose、Kubernates等。Dokcer相对来说更简单直接,K8s则更强大复杂。
HTPP协议的Expext 100-continue导致的“操作超时”
莫名其妙的“操作超时”
在用C#的HttpWebRequest写一个HTTP客户端请求时,遇到了一个莫名其妙的问题,就是在发送POST请求时,总是报“操作超时”的错误。核心代码如下:
1 | ... |
在执行bRequest.GetResponse()
时会卡住,一直等待直到报“操作超时”的错误。
分析与排查
代码问题的几率很小
这段代码没啥好说的,是老系统里千锤百炼留下来的基础代码。从网络上找到的教程什么的,大致也是这样写的,所以代码的问题的几率很小。
也不是服务端处理慢
服务端的响应不涉及复杂的业务处理,这个可以直接排除。
用Postman测试可以正常访问
用Postman测试,没有出现“操作超时”的错误。这个问题就很奇怪了,Postman的请求和代码里的请求应该是一样的,为什么Postman可以正常访问,而代码里就不行呢?
用Fiddler抓包分析
只有用Fiddler抓包分析,来看看代码的request跟Postman的请求有什么差异。发现代码里的请求,主要差异是多了一个Expect: 100-continue
的Header。
Postman复现问题
Postman加上100-continue的Header,就可以复现“操作超时”的问题。
罪魁祸首之100-continue
查了一下资料,100-continue是HTTP 1.1里设计的一个状态码,在发送请求体之前,先发送一个Expect: 100-continue
,如果服务器响应了100-continue
,那么就会继续发送请求体。
这个设计的目的是为了在发送大量数据时,先确认服务器是否接受这个请求,如果不接受,就不用发送大量的数据了,从而减少网络带宽的浪费。
这就跟本文的问题对上了,刚好是带请求体的POST请求,所以先发送Expect: 100-continue
,但是服务器没有响应100-continue
,就一直等待到“操作超时”。
解决方案
定位到具体的原因后,解决起来就容易了,有两种方案(任选其一):
客户端:禁用100-continue
1 | wbRequest.ServicePoint.Expect100Continue = false; |
服务端:支持100-continue或者忽略100-continue
这个得看服务端的网关是什么了,可以配置为HTTP协议为1.1,或者把请求头里的Expect: 100-continue
过滤掉。
配置Nginx支持TLS 1.0和1.1
未能创建 SSL/TLS 安全通道
最近将服务器升级到Ubuntu 22.04.2 LTS后,部分终端的.Net framework应用连接时报错:“请求被中止:未能创建SSL/TLS 安全通道”。
这个问题以前也出现过,终端的操作系统是Windows 7,只能安装.Net Framefork 4.0,但是4.0不支持TLS1.2,而Ubuntu升级后不支持TLS1.0和1.1,这就导致无法建立SSL/TLS安全通道。
当时主要参考 ubuntu不支持tls1.0解决,修改openssl的配置/etc/ssl/openssl.cnf
1 | //在第一行增加: |
Ubuntu升级过程中,都是选择的维持现有配置,所以/etc/ssl/openssl.cnf里还是有这些配置,不知道为什么没有生效。
修改Nginx的配置
修改nginx的配置:
1 | ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:@SECLEVEL=1"; |
使用openssl测试
1 | openssl s_client -connect xiaoboey.top:443 -tls1_1 |
还是没解决。。。
在桌面应用里使用EventSource来代替直连RabbitMQ
Event Source,即Server-sent events,主要优点是基于HTTP协议进行长连接,除了在网页里用JavaScript可以接收消息,其他的应用只要支持HTTP协议都没问题;而RabbitMQ完整实现了AMQP协议,即Advanced Message Queuing Protocol,非常成熟稳定。本文所谓的“代替”,适合的场景非常有限,如果要追求消息推送的稳定可靠,还是建议直接使用RabbitMQ。