使用 sealos 部署 Kubernetes 集群

今天介绍使用 sealos 一键部署 Kubernetes 集群,sealos 是只能用丝滑一词形容的 kubernetes 高可用安装(kubernetes install)工具,一条命令,离线安装,包含所有依赖,内核负载不依赖 haproxy keepalived,纯 golang 开发,99 年证书,支持 v1.20.0 v1.19.5 v1.18.13 v1.17.15! sealos 支持的环境 Linux 发行版,CPU 架构 Debian 9+, x86_64/ arm64 Ubuntu 16.04, 18.04, 20.04, x86_64/ arm64 Centos/RHEL 7.6+, x86_64/ arm64 其他支持 systemd 的系统环境。x86_64/ arm64 Kylin arm64 kubernetes 版本 1.16+ 1.17+ 1.18+ 1.19+ 1.20+ 1.21+ 1.22+ 要求和建议 最低资源要求 2 vCpu 4G Ram 40G+ 存储 操作系统要求 ssh 可以访问各安装节点 各节点主机名不相同,并满足 kubernetes 的主机名要求。 各节点时间同步 网卡名称如果是不常见的,建议修改成规范的网卡名称,如 (eth.|en.|em.*) kubernetes1.20+ 使用 containerd 作为 cri. 不需要用户安装 docker/containerd. sealos 会安装 1.3.9 版本 containerd。 kubernetes1.19 及以下 使用 docker 作为 cri。也不需要用户安装 docker。sealos 会安装 1.19.03 版本 docker 网络和 DNS 要求: ...

十月 26, 2021 · overstarry

kratos 自定义 handler func 没有请求日志的问题及解决

出现的问题 最近在使用 kratos 开发 api 的时候,由于通过 proto 生成的 server handler 不符合业务的需求,需要通过自定义 handlerFunc 来定义接口。在开发中为了程序的可观测性,我使用了 kratos 提供的 logging 中间件。 在使用的过程中,我发现自定义的 HandlerFunc 的请求日志没有显示,而 proto 生成的请求正确显示了。 问题的原因 为了找到出现这种情况的原因,我在官方的 Github 仓库提了个 issue(#1566), 得到了维护人员的解答。 出现这种情况的原因是 自己定义的 handlerFunc 不走 middleware 中间件,需要自定义 http filter 才能解决。 解决 经过对 http filter 例子的简单研究,参考了官方的 logging 中间件,我自己实现了 logging filter. 代码: package middleware import ( "fmt" "net/http" "time" "github.com/go-kratos/kratos/v2/errors" "github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/transport" ) func Server(logger log.Logger) func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var ( code int32 reason string kind string operation string ) ctx := r.Context() startTime := time.Now() if info, ok := transport.FromServerContext(ctx); ok { kind = info.Kind().String() operation = info.Operation() } next.ServeHTTP(w, r) if se := errors.FromError(nil); se != nil { code = se.Code reason = se.Reason } level, stack := extractError(nil) _ = log.WithContext(ctx, logger).Log(level, "kind", "server", "component", kind, "operation", operation, "args", extractArgs(r), "code", code, "reason", reason, "stack", stack, "latency", time.Since(startTime).Seconds(), ) }) } } // extractArgs returns the string of the req func extractArgs(req interface{}) string { if stringer, ok := req.(fmt.Stringer); ok { return stringer.String() } return fmt.Sprintf("%+v", req) } // extractError returns the string of the error func extractError(err error) (log.Level, string) { if err != nil { return log.LevelError, fmt.Sprintf("%+v", err) } return log.LevelInfo, "" } 顺利的显示了请求的日志: ...

十月 22, 2021 · overstarry

Rsstest

test

十月 22, 2021 · overstarry

golang 随机 time.Sleep 出现的问题

问题 最近需要使用 rand 包随机 time.Sleep() 的时间,我的代码是这样的: package main import ( "math/rand" "time" ) func main() { rand.Seed(time.Now().UTC().UnixNano()) n := rand.Intn(10) time.Sleep(n * time.Second) } 会遇到下面的问题: Cannot use 'n * time.Second' (type int) as the type Duration Invalid operation: n * time.Second (mismatched types int and Duration) 解决的方法 使用 time.Duration 转换类型,代码如下: package main import ( "math/rand" "time" ) func main() { rand.Seed(time.Now().UTC().UnixNano()) n := rand.Intn(10) time.Sleep(time.Duration(n) * time.Second) } 问题的原因 time.Sleep 方法接收的类型是 Duration 类型。 func Sleep(d Duration) 当我们要 sleep 5s 时,参数是 5 * time.Second, Second 又是 1000 * Millisecond, Millisecond 是 1000 * Microsecond,Microsecond 是 1000 * Nanosecond,Nanosecond 是 1 纳秒,它的类型就是 Duration。最后 5s 就变成 5000000000 数值。 ...

十月 15, 2021 · overstarry

如何在 gin 中查看 Prometheus 指标

在我们的 go 应用程序中,我们如果想要查看应用程序的相关指标,该如何操作呢? 解决 Prometheus 的官方 pkg 提供了 promhttp.Handler() 方法,但是该方法返回了一个 http.Handler 接口, 不满足 gin 所使用的类型,我们采用其他的方法进行。 具体的代码: promhttp.InstrumentMetricHandler(prometheus.DefaultRegisterer, promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{ DisableCompression: true, })).ServeHTTP(c.Writer, c.Request) 通过在路由处理函数中添加此代码,就能顺利的展示与应用程序相关的指标。 如果想要自定义指标,你只需将自定义的指标进行相应的注册。 参考链接 https://github.com/prometheus/client_golang

九月 30, 2021 · overstarry

使用 Prometheus 收集 MinIO 指标

今天我来讲一讲如何使用 Prometheus 获取 MinIO 指标。 前提 需要部署好 Prometheus、Minio 服务和配置好 Minio Client , MinIO 和 Prometheus 的网络需要可互相访问。 步骤 1. 生成 JWT 令牌 使用以下命令生成 JWT bearer token mc admin Prometheus generate ALIAS 请将 ALIAS 替换成你的 MinIO 主机服务名。 该命令会产生如下的信息输出: scrape_configs: - job_name: minio-job bearer_token: token metrics_path: /minio/v2/metrics/cluster scheme: http static_configs: - targets: [minIOip] 配置 Prometheus Targets 将上一个步骤输出的信息添加至 Targets 配置文件 (Prometheus.yml) 中,重新启动 Prometheus 服务。 查询 Prometheus 指标 添加重启完 Prometheus 服务后,我们就可以在 Prometheus 界面查询 Minio 相关的指标。例如:我们可以通过 minio_bucket_usage_object_total 指标查询 bucket 的对象总数。 ...

九月 28, 2021 · overstarry

分布式链路追踪初探 2

上一篇文章介绍了分布式链路的标准 OpenTracing, 在 OpenTracing 的官网我们可以看到这样一条信息 OpenTracing and OpenCensus have merged to form OpenTelemetry!。 可以看到 OpenTracing 和 OpenCensus 已经被合并为 OpenTelemetry 了。 OpenCensus 是什么呢?OpenTracing 是最早为分布式追踪制定了一套平台无关、厂商无关的协议标准的项目,并以此成为了 CNCF 的孵化项目。在之后,谷歌牵头,微软加入,创建了 OpenCensus 项目统一 Metrics 基础指标监控的使用方式,还做了 OpenTracing 的老本行:分布式追踪。 OpenTelemetry OpenTelemetry 的自身定位十分明确:数据采集和标准规范的统一,对于数据如何去使用、存储、展示、告警,官方是不涉及的。 OpenTelemetry 的终极目标十分伟大:实现 Metrics、Tracing、Logging 的融合及大一统,作为 APM 的数据采集终极解决方案。 目前 OpenTelemetry 正式成为 CNCF 的孵化项目,OpenTracing 和 OpenCensus 不再维护,OpenTracing 目前是 CNCF 的存档项目。 OpenTelemetry 的一些基础知识是兼容 OpenTracing 的,只有一些 API 是不同的。 OpenTelemetry for go 我们继续使用上文的代码,对上文的代码进行修改。 install 依赖 go get go.opentelemetry.io/[email protected] go.opentelemetry.io/otel/[email protected] go.opentelemetry.io/otel/exporters/stdout/[email protected] go.opentelemetry.io/otel/[email protected] go get -u go.opentelemetry.io/otel/exporters/jaeger OpenTelemetry 官方为多种开源框架提供了开箱即用的 Instrumentation Packages,如 gin , beego , mux , go-kit 等,当然也支持 net/http 标准库 ,更多可浏览 opentelemetry-go-contrib 仓库。 ...

九月 24, 2021 · overstarry

分布式链路追踪初探

微服务架构 作为云原生核心技术之一,提倡将单体应用程序 (巨石架构) 划分成一组小的服务(微服务),服务之间互相协调、互相配合,为用户提供最终价值。 微服务架构设计中,通常由多个微服务组件组成,有 1) API 网关 ( apisix, kong, traefik ) 负责认证鉴权、负载均衡、限流和静态响应处理; 2) 服务注册发现中心 ( ZooKeeper、Consul、ETCD ) ,负责服务的注册和发现。3) 可观测性 负责日志收集查看的 ELK、Loki,负责服务性能指标告警的指标 Metrics 监控 Prometheus, 负责追踪请求的 Tracing 链路追踪。在多个组件的组成下,才能顺利组成一个好的微服务架构。 今天我就来简单的讲一讲微服务组成中可观测性的分布式链路追踪。 OpenTracing 介绍 OpenTracing 是一个新的、开放的分布式追踪标准,用于应用程序和 OSS 包。有过大规模构建微服务经验的开发者都知道分布式追踪的作用和重要性:每个进程的日志和指标监控都有它们的用武之地,但它们都无法重建事务在分布式系统中传播时的复杂旅程。分布式跟踪就是这些旅程。 OpenTracing 项目定义了一套分布式追踪的标准,以统一各种分布式追踪系统的实现。OpenTracing 中包含了一套分布式追踪的标准规范,各种语言的 API,以及实现了该标准的编程框架和函数库。 OpenTracing 提供了平台无关、厂商无关的 API,因此开发者只需要对接 OpenTracing API,无需关心后端采用的到底是什么分布式追踪系统,Jager、Skywalking、LightStep 等都可以无缝切换。 数据模型 OpenTracing 定义了以下数据模型: Trace(调用链):一个 Trace 代表一个事务或者流程在(分布式)系统中的执行过程。例如来自客户端的一个请求从接收到处理完成的过程就是一个 Trace。 Span(跨度):Span 是分布式追踪的最小跟踪单位,一个 Trace 由多段 Span 组成。可以被理解为一次方法调用,一个程序块的调用,或者一次 RPC/数据库访问。只要是一个具有完整时间周期的程序访问,都可以被认为是一个 Span。 SpanContext(跨度上下文):分布式追踪的上下文信息,包括 Trace id,Span id 以及其它需要传递到下游服务的内容。一个 OpenTracing 的实现需要将 SpanContext 通过某种序列化协议 (Wire Protocol) 在进程边界上进行传递,以将不同进程中的 Span 关联到同一个 Trace 上。对于 HTTP 请求来说,SpanContext 一般是采用 HTTP header 进行传递的。 ...

九月 18, 2021 · overstarry

遍历 map 列表的 Golang 模板

遍历 map 列表的 Golang 模板遇到的问题及解决方式 出现了什么问题? 今天在使用 go template 渲染文本的时候,在运行的时候,遇到了一个问题导致渲染不成功,具体的问题是: 2021/09/10 09:47:05 template: test:2:3: executing "test" at <.Attributes>: can't evaluate field Attributes in type interface {} 具体的代码如下: package main import ( "log" "os" "strings" "text/template" ) type TestData struct { Name string `json:"name"` Attributes map[string]interface{} } const testTemplate = `{{ range $key, $value := .Attributes }} {{.Name}} {{ $key }}: {{ $value }}{{- end }}` func main() { tmpl, err := template.New("test").Parse(strings.TrimSpace(testTemplate)) if err != nil { log.Println(err) return } data := TestData{ "hello", map[string]interface{}{ "key": "hello", "value": "json", }, } err = tmpl.Execute(os.Stdout, data) if err != nil { log.Println(err) return } } 问题出现的原因? 模板在 range 循环中会把。设置为当前 Attributes 变量,在 Attributes 变量中没有 name 这个成员结构,这就导致模板没有渲染成功。 ...

九月 10, 2021 · overstarry

Golang Templates

Golang Template 今天来讲讲 golang 中的标准库 template, Go 标准库提供了几个 package 可以产生输出结果,主要有 2 个:text/template 和 html/template, text/template 提供根据模板输出内容,html/template 产生安全的 HTML 的输出,这两个库的使用方式很相似,文中的例子大部分是基于 html/template 展示的。 解析和创建模板 模板命名 template 所使用的库没有限定扩展名,但最经常使用的后缀是 .tmpl, 编辑器对.tmpl 的支持最好,官方的例子也是使用 .tmpl, .tpl 也经常使用。 创建模板 通过 Parse 方法可以创建文件名为名字的模板。 package main import ( "fmt" "html/template" "log" ) func main() { tpl, err := template.New("index").Parse("index.tmpl") if err != nil { log.Fatalln(err) } } 解析多个模板 通过 template.ParseFiles(filenames …string) 方法可以解析一组模板,使用各个文件名作为模板名称。 template.ParseGlob(pattern) 方法会根据 pattern 解析所有匹配的模板并保存。 package main import "html/template" func main() { template.ParseFiles("index.tmpl", "index2.tmpl") } 解析字符串模板 除了可以解析文件,还可以解析字符串模板。 ...

九月 3, 2021 · overstarry