Rancher Cattle Cluster Agent Could not Resolve Host

起因 最近在使用 rancher 导入外部 k8s 集群时,遇到了一个问题:在要导入的集群上执行命令后,创建的 pod 运行错误,错误日志大概如下: INFO: Environment: CATTLE_ADDRESS=100.66.209.198 CATTLE_CA_CHECKSUM= CATTLE_CLUSTER=true CATTLE_CLUSTER_AGENT_PORT=tcp://11.11.10.11:80 CATTLE_CLUSTER_AGENT_PORT_443_TCP=tcp://11.11.10.11:443 CATTLE_CLUSTER_AGENT_PORT_443_TCP_ADDR=10.96.0.125 CATTLE_CLUSTER_AGENT_PORT_443_TCP_PORT=443 CATTLE_CLUSTER_AGENT_PORT_443_TCP_PROTO=tcp CATTLE_CLUSTER_AGENT_PORT_80_TCP=tcp://10.96.0.125:80 CATTLE_CLUSTER_AGENT_PORT_80_TCP_ADDR=10.96.0.125 CATTLE_CLUSTER_AGENT_PORT_80_TCP_PORT=80 CATTLE_CLUSTER_AGENT_PORT_80_TCP_PROTO=tcp CATTLE_CLUSTER_AGENT_SERVICE_HOST=10.96.0.125 CATTLE_CLUSTER_AGENT_SERVICE_PORT=80 CATTLE_CLUSTER_AGENT_SERVICE_PORT_HTTP=80 CATTLE_CLUSTER_AGENT_SERVICE_PORT_HTTPS_INTERNAL=443 CATTLE_CLUSTER_REGISTRY= CATTLE_INGRESS_IP_DOMAIN=sslip.io CATTLE_INSTALL_UUID=333850e4-f500-43a2-a359-e1dfd94e4f35 CATTLE_INTERNAL_ADDRESS= CATTLE_IS_RKE=false CATTLE_K8S_MANAGED=true CATTLE_NODE_NAME=cattle-cluster-agent-55b9954958-5679q CATTLE_SERVER=https://xx.xx.vip CATTLE_SERVER_VERSION=v2.6.6 INFO: Using resolv.conf: search cattle-system.svc.cluster.local svc.cluster.local cluster.local nameserver 10.96.0.10 options ndots:5 ERROR: https://xx.xx.vip/ping is not accessible (Could not resolve host: xx.xx.vip) 可以很好的看出错误的原因是域名 dns 解析错误。 解决 在发现问题后,可以根据错误日志进行相应的解决,我们先查看 coredns 的日志 kubectl logs deployment/coredns -n kube-system [ERROR] plugin/errors: 2 XX.XX.vip. A: read udp 100.108.11.198:32988->100.100.2.136:53: i/o timeout [ERROR] plugin/errors: 2 XX.XX.vip. A: read udp 100.108.11.198:53477->100.100.2.136:53: i/o timeout [ERROR] plugin/errors: 2 XX.XX.vip. AAAA: read udp 100.108.11.198:40436->100.100.2.136:53: i/o timeout 可以看到相应域名解析错误,根据以前的经验,先重启 coredns 容器尝试是否能解决问题,重启后发现问题未能解决 (可能需要重启相应节点的机器。 ...

六月 16, 2023 · 1 分钟 · overstarry

sealos version compare error

前言 最近在使用 sealos 安装更新 k8s 的过程中发现了一个问题:nfo new cluster version v1.25.10 behind the current version v1.25.8。 现在我来简单描述下过程:我想要将 k8s 版本从 v1.25.8 升级到 v1.25.10,运行更新命令:sealos run labring/kubernetes:v1.25.10-4.2.0 -f 后,出现了以下错误信息: 2023-06-09T11:30:06 info new cluster version v1.25.10 behind the current version v1.25.8 ,通过对错误信息的理解,发现提示 v1.25.10 版本比 v1.25.8 小,通过我对版本号的理解,这应该是个错误。 发现及解决问题 发现了问题,接下来要寻找出现问题的代码和解决问题。通过 Github 的代码搜索功能搜索关键字 behind the current version 顺利找到问题代码所在。 对找到的代码进行分析,发现是 versionutil.Compare(curversion, version) 方法出现了错误,我们来看看这个函数的代码: func Compare(v1, v2 string) bool { v1 = strings.Replace(v1, "v", "", -1) v2 = strings.Replace(v2, "v", "", -1) v1 = strings.Split(v1, "-")[0] v2 = strings.Split(v2, "-")[0] v1List := strings.Split(v1, ".") v2List := strings.Split(v2, ".") if len(v1List) != 3 || len(v2List) != 3 { logger.Error("error version format %s %s", v1, v2) return false } if v1List[0] > v2List[0] { return true } else if v1List[0] < v2List[0] { return false } if v1List[1] > v2List[1] { return true } else if v1List[1] < v2List[1] { return false } if v1List[2] >= v2List[2] { return true } return false } 通过对代码的分析,发现是对主次修订版本号对比时出现了问题,代码中是简单的使用了字符串比较,字符串数字比较会以字典序进行比较,所以会出现 “8” 大于 “10"的情况。正常的数字比较应该是将字符串转为数字进行相应比较。 ...

六月 10, 2023 · 2 分钟 · overstarry

Kubernetes pod 修改 hosts 文件

前言 最近看了 k8s 的书,学习了一些新的知识,将会分几篇来介绍学习到的知识,本文来先介绍 k8s 中如何修改 pod 的 hosts 文件。 我们知道当 DNS 出现问题时,可以向 Pod 的/etc/hosts 文件添加条目来提供主机名解析 Pod 级别覆盖。该如何向 hosts 文件中添加条目呢?可以使用 PodSpec 中的 HostAliases 字段添加自定义条目。 虽然我们也可以直接进入 pod 修改 host 文件来实现,但这样 pod 重建时会被覆盖,所以我们应该使用 HostAliases 来进行修改,因为该文件会由 Kubelet 管理,并且 可以在 Pod 创建/重启过程中被重写。 使用 我们该如何操作呢,接下来由我来介绍使用步骤: 1 先创建 Deployment YAML 文件来创建后台运行的 busybox pod apiVersion: apps/v1 kind: Deployment metadata: name: busybox-deployment spec: replicas: 1 selector: matchLabels: app: busybox template: metadata: labels: app: busybox spec: containers: - name: busybox image: busybox args: [ "sleep", "3600" ] resources: limits: memory: "128Mi" cpu: "500m" requests: memory: "64Mi" cpu: "250m" volumeMounts: - name: busybox-volume mountPath: /data volumes: - name: busybox-volume emptyDir: {} 查看 pod ip ...

六月 3, 2023 · 1 分钟 · overstarry

Apisix 忽略 uri 大小写

前言 最近需要忽略请求 uri 大小写,即不管 uri 的大小写都返回小写 uri 所请求的响应内容,例如请求 xx.vip/A 实际请求 xx.vip/a, 本文主要以 apisix 来讲解如何实现这个功能。 解决 遇到这个需求,首先肯定采用 apisix 的插件来实现,根据前面多次的经验,这个功能应该可以使用 serverless 插件中的 serverless-pre-function 插件来实现,具体的流程如下: 1 获取请求的 uri 2 将 uri 转为小写 3 修改请求的 uri 具体的插件内容如下: "serverless-pre-function": { "_meta": { "disable": false }, "functions": [ "return function(conf, ctx) local uri = ctx.var.uri;ctx.var.uri= string.lower(uri);ngx.log(ngx.ERR, \"match uri \", ctx.var.uri ); end" ], "phase": "rewrite" } 添加插件后,再次请求路径,发现请求结果还是没有变,查看日志发现 uri 修改成功了,不知为何还是没有修改成功。 后面又仔细研究了 proxy-rewrite 插件中修改 uri 的代码,发现它是使用了 nginx 标准的函数 ngx.req.set_uri 来赋值新的 uri。 ...

五月 26, 2023 · 1 分钟 · overstarry

sqlc 初体验

简介 sqlc 可以生成从 SQL 生成类型安全代码。它的工作原理是: 使用 SQL 书写查询语句。 运行 sqlc 生成 Go 代码,该代码为这些查询提供类型安全的接口。 在应用程序代码中调用生成的代码与数据库进行交互。 安装 sqlc 有多种安装方式: macOS: brew install sqlc Ubuntu: sudo snap install sqlc go 安装: # Go >= 1.17: go install github.com/kyleconroy/sqlc/cmd/sqlc@latest # Go < 1.17: go get github.com/kyleconroy/sqlc/cmd/sqlc docker 安装: docker pull kjconroy/sqlc 其它: https://github.com/kyleconroy/sqlc/releases 入门使用 插件 sqlc.yaml 首先创建 sqlc.yaml 文件,sqlc 会在当前目录下查找 sqlc.yaml 或 sqlc.json 文件。 # sqlc.yaml version: 1 packages: - path: "tutorial" name: "tutorial" engine: "mysql" schema: "schema.sql" queries: "query.sql" 创建 sql 文件 sqlc 需要得知数据库表结构和相应的 sql 语句,我们创建 schema.sql 定义表结构: ...

五月 20, 2023 · 3 分钟 · overstarry

Apisix Docker 部署网站重定向端口错误问题

前言 前段时间在使用 apisix 添加路由时,需要将 http 转为 https, 在配置 http_to_https 后,访问相应网址时发现 https 的端口不是我们所配置的默认端口 443,而是 9443 端口。 可以看到访问 http://localhost 会跳转至错误的地址:https://localhost:9443/ ,正确的地址应该是 https://localhost,这是怎么回事呢? 分析 接下来我来简单对问题进行简单分析。 我是采用 docker 的方式部署的 apisix,这是我们的配置文件: version: "3" services: apisix-dashboard: image: apache/apisix-dashboard:3.0.0-alpine restart: always volumes: - ./dashboard_conf/conf.yaml:/usr/local/apisix-dashboard/conf/conf.yaml ports: - "9000:9000" networks: apisix: apisix: image: apache/apisix:${APISIX_IMAGE_TAG:-3.2.0-debian} restart: always volumes: - ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro depends_on: - etcd ##network_mode: host ports: - "9180:9180/tcp" - "80:9080/tcp" - "9091:9091/tcp" - "443:9443/tcp" - "9092:9092/tcp" networks: apisix: etcd: image: bitnami/etcd:3.4.15 restart: always volumes: - etcd_data:/bitnami/etcd environment: ETCD_ENABLE_V2: "true" ALLOW_NONE_AUTHENTICATION: "yes" ETCD_ADVERTISE_CLIENT_URLS: "http://etcd:2379" ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379" ports: - "2379:2379/tcp" networks: apisix: web1: image: nginx:1.19.0-alpine restart: always volumes: - ./upstream/web1.conf:/etc/nginx/nginx.conf ports: - "9081:80/tcp" environment: - NGINX_PORT=80 networks: apisix: networks: apisix: driver: bridge volumes: etcd_data: driver: local 可以看到我们将 apisix 容器的 http 端口和 https 端口映射为 80 和 443,按照常理来说,http_to_https 后的端口应该也是 443 端口才对。我猜测重定向时,apisix 还是采用配置文件中设定的 https 端口才导致跳转的 url 端口错误。 ...

五月 13, 2023 · 1 分钟 · overstarry

Go wasi

WebAssembly 是一种新的编码方式,可以在现代的网络浏览器中运行 - 它是一种低级的类汇编语言,具有紧凑的二进制格式,可以接近原生的性能运行,并为诸如 C / C ++等语言提供一个编译目标,以便它们可以在 Web 上运行。它也被设计为可以与 JavaScript 共存,允许两者一起工作。 Go 从 1.11 版本就开始支持将 Go 源码编译为 wasm 二进制文件,并在支持 wasm 的浏览器环境中运行。 不过 WebAssembly 绝不仅仅被设计为仅限于在 Web 浏览器中运行,核心的 WebAssembly 语言是独立于其周围环境的,WebAssembly 完全可以通过 API 与外部世界互动。在 Web 上,它自然使用浏览器提供的现有 Web API。然而,在浏览器之外,之前还没有一套标准的 API 可以让 WebAssembly 程序使用。这使得创建真正可移植的非 Web WebAssembly 程序变得困难。WebAssembly System Interface(WASI) 是一个填补这一空白的倡议,它有一套干净的 API,可以由多个引擎在多个平台上实现,并且不依赖于浏览器的功能(尽管它们仍然可以在浏览器中运行)。 Go 1.21 将增加对 WASI 的支持,初期先支持 WASI Preview1 版本,之后会支持 WASI Preview2 版本,直至最终 WASI API 版本发布! go 编译支持 wasi 的程序 怎么样才能编译支持 wasi 的程序呢?我们可以使用 GOOS=wasip1 GOARCH=wasm 将 Go 源码编译为支持 WASI 的 wasm 程序。下面是一个例子: ...

五月 2, 2023 · 1 分钟 · overstarry

Go 实现简单反向代理

前言 说起反向代理,大家应该都不陌生,是指以代理服务器来接受 internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 internet 上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。常见的反向代理有 Nginx,HAProxy,Apisix 等。 接下来介绍如何使用 go 实现一个反向代理服务器。 golang 实现 使用 golang 实现反向代理非常简单,标准库 net/http/httputil 提供了反向代理的方法可以让我们方便的实现反向代理,使我们可以很快的实现一个简单的反向代理服务器。 package main import ( "log" "net/http" "net/http/httputil" "net/url" ) func NewProxy(targetHost string) (*httputil.ReverseProxy, error) { url, err := url.Parse(targetHost) if err != nil { return nil, err } return httputil.NewSingleHostReverseProxy(url), nil } func ProxyRequestHandler(proxy *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { proxy.ServeHTTP(w, r) } } func main() { proxy, err := NewProxy("https://overstarry.vip") if err != nil { panic(err) } http.HandleFunc("/", ProxyRequestHandler(proxy)) log.Fatal(http.ListenAndServe(":8080", nil)) } 这段代码将到达我们代理服务器的任何请求都会被代理到 https://overstarry.vip。我们运行代码,访问网站,发现 403 Forbidden 好像请求被拦截了,应该是源网站进行了请求校验,这该怎么处理呢?通过查阅资料得知,我们需要将 host 传递过去,修改后的代码如下: package main import ( "log" "net/http" "net/http/httputil" "net/url" ) func NewProxy(targetHost string) (*httputil.ReverseProxy, error) { url, err := url.Parse(targetHost) if err != nil { return nil, err } return httputil.NewSingleHostReverseProxy(url), nil } func ProxyRequestHandler(proxy *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { r.Host = "overstarry.vip" proxy.ServeHTTP(w, r) } } func main() { proxy, err := NewProxy("https://overstarry.vip") if err != nil { panic(err) } http.HandleFunc("/", ProxyRequestHandler(proxy)) log.Fatal(http.ListenAndServe(":8080", nil)) } 现在运行代码即可正常访问了。 ...

四月 8, 2023 · 2 分钟 · overstarry

CertificateManager 使用 dns 授权申请证书 -- gcloud 方式

本文讲解如何使用 dns 授权方式申请 google cloud 证书,通过查阅官方文档可以得知可以使用 gcloud 和 Certificate Manager API 来申请证书,本文使用 gcloud 命令行工具来执行步骤。 创建 DNS 授权 第一步是创建 DNS 授权,使用以下命令来创建: gcloud certificate-manager dns-authorizations create AUTHORIZATION_NAME \ --domain="DOMAIN_NAME" gcloud certificate-manager dns-authorizations describe AUTHORIZATION_NAME 需要将 AUTHORIZATION_NAME 和 DOMAIN_NAME 分别替换为 dns 授权的名称和相应的域名。 先创建 dns 授权然后查看授权的详细信息 gcloud certificate-manager dns-authorizations create overstarry --domain="overstarry.vip" gcloud certificate-manager dns-authorizations describe overstarry 根据返回的 cname 信息,需要到相应的域名解析中添加 cname 记录。 创建引用 DNS 授权的 Google 管理的证书 接下来 创建引用 DNS 授权的 Google 管理的证书,使用以下命令创建: ...

三月 29, 2023 · 2 分钟 · overstarry

Google Cloud 清除 CDN 缓存

最近在研究使用 google cloud 的 cdn 服务,本文就来讲解如何清除 cdn 的缓存。 本文介绍了几种清除 cdn 缓存的方法。 google cloud console 清除 第一种也是最简单的,就是直接从 google cloud console 后台进行操作,我们打开 console 后台,选择网络服务,点击负载均衡界面,选择我们要清除的 cdn 缓存所使用的负载均衡器,点击缓存页面, 输入想要 cdn 节点清除的路径即可。过了一会,就可以看到操作成功,相应的文件已经失效。 Google Cloud CLI 命令 第二种方法是使用 Google Cloud CLI 使 cdn 缓存文件失效。 Google Cloud CLI 安装 该怎么安装 Google Cloud CLI 呢,有 2 个办法:1) 直接下载安装二进制文件 2) 使用 Cloud Shell. 本文是使用 Cloud Shell 进行的操作。 使缓存内容失效 1 使用 gcloud compute url-maps list 列出目前所使用的负载均衡器 ...

三月 25, 2023 · 1 分钟 · overstarry