golang Kubernetes微服务最佳实践演示插件podinfo的使用
Golang Kubernetes微服务最佳实践演示插件podinfo的使用
Podinfo简介
Podinfo是一个用Go编写的小型Web应用程序,展示了在Kubernetes中运行微服务的最佳实践。它被CNCF项目如Flux和Flagger用于端到端测试和研讨会。
主要特性
- 健康检查(就绪和存活)
- 中断信号上的优雅关闭
- 用于秘密和配置映射的文件观察器
- 使用Prometheus和Open Telemetry进行仪器化
- 使用zap的结构化日志记录
- 使用viper的12-factor应用
- 故障注入(随机错误和延迟)
- Swagger文档
- Timoni、Helm和Kustomize安装程序
- 使用Kubernetes Kind和Helm进行端到端测试
- 使用Docker buildx和GitHub Actions的多架构容器镜像
- 使用Sigstore cosign进行容器镜像签名
- 嵌入容器镜像中的SBOM和SLSA Provenance
- 使用govulncheck进行CVE扫描
Web API
GET /
打印运行时信息GET /version
打印podinfo版本和git提交哈希GET /metrics
返回HTTP请求持续时间和Go运行时指标GET /healthz
由Kubernetes存活探针使用GET /readyz
由Kubernetes就绪探针使用POST /readyz/enable
向Kubernetes LB发出信号,表示此实例已准备好接收流量POST /readyz/disable
向Kubernetes LB发出信号,停止向此实例发送请求GET /status/{code}
返回状态代码GET /panic
以退出代码255崩溃进程POST /echo
将调用转发到后端服务并回显发布的内容GET /env
将环境变量作为JSON数组返回GET /headers
返回带有请求HTTP头的JSONGET /delay/{seconds}
等待指定的时间段POST /token
发行有效期为一分钟的JWT令牌GET /token/validate
验证JWT令牌GET /configs
返回带有安装在config
卷中的配置映射和/或秘密的JSONPOST/PUT /cache/{key}
将发布的内容保存到RedisGET /cache/{key}
如果键存在,则从Redis返回内容DELETE /cache/{key}
如果存在,则从Redis删除键POST /store
将发布的内容写入磁盘上的/data/hash并返回内容的SHA1哈希GET /store/{hash}
如果存在,则返回文件/data/hash的内容GET /ws/echo
通过websockets回显内容GET /chunked/{seconds}
使用transfer-encoding
类型chunked
给出部分响应,然后等待指定的时间段GET /swagger.json
返回API Swagger文档,用于Linkerd服务分析和Gloo路由发现
安装
要在Kubernetes上安装Podinfo,最低要求的版本是Kubernetes v1.23。
Timoni安装
timoni -n default apply podinfo oci://ghcr.io/stefanprodan/modules/podinfo
Helm安装
从github.io安装:
helm repo add podinfo https://stefanprodan.github.io/podinfo
helm upgrade --install --wait frontend \
--namespace test \
--set replicaCount=2 \
--set backend=http://backend-podinfo:9898/echo \
podinfo/podinfo
helm test frontend --namespace test
helm upgrade --install --wait backend \
--namespace test \
--set redis.enabled=true \
podinfo/podinfo
从ghcr.io安装:
helm upgrade --install --wait podinfo --namespace default \
oci://ghcr.io/stefanprodan/charts/podinfo
Kustomize安装
kubectl apply -k github.com/stefanprodan/podinfo//kustomize
Docker安装
docker run -dp 9898:9898 stefanprodan/podinfo
持续交付
要在Kubernetes集群上安装podinfo并自动保持最新版本,您可以使用Flux。
在MacOS和Linux上使用Homebrew安装Flux CLI:
brew install fluxcd/tap/flux
安装Helm操作所需的Flux控制器:
flux install \
--namespace=flux-system \
--network-policy=false \
--components=source-controller,helm-controller
将podinfo的Helm存储库添加到您的集群,并配置Flux每十分钟检查一次新图表版本:
flux create source helm podinfo \
--namespace=default \
--url=https://stefanprodan.github.io/podinfo \
--interval=10m
创建一个podinfo-values.yaml
文件:
cat > podinfo-values.yaml <<EOL
replicaCount: 2
resources:
limits:
memory: 256Mi
requests:
cpu: 100m
memory: 64Mi
EOL
为在默认命名空间中部署podinfo创建一个Helm release:
flux create helmrelease podinfo \
--namespace=default \
--source=HelmRepository/podinfo \
--release-name=podinfo \
--chart=podinfo \
--chart-version=">5.0.0" \
--values=podinfo-values.yaml
要检查当前部署的版本:
flux get helmreleases -n default
要从集群中删除podinfo的Helm存储库和release:
flux -n default delete source helm podinfo
flux -n default delete helmrelease podinfo
更多关于golang Kubernetes微服务最佳实践演示插件podinfo的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang Kubernetes微服务最佳实践演示插件podinfo的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Kubernetes微服务最佳实践:Podinfo演示插件使用指南
Podinfo是一个轻量级的Go微服务示例,专门设计用于演示Kubernetes最佳实践。下面我将详细介绍如何使用Podinfo以及相关的Golang代码示例。
1. Podinfo概述
Podinfo提供以下功能:
- HTTP和gRPC API端点
- 指标导出(Prometheus格式)
- 就绪/存活探针
- 混沌测试注入
- 配置管理
- 结构化日志记录
2. 部署Podinfo
基本部署YAML
apiVersion: apps/v1
kind: Deployment
metadata:
name: podinfo
spec:
replicas: 2
selector:
matchLabels:
app: podinfo
template:
metadata:
labels:
app: podinfo
annotations:
prometheus.io/scrape: "true"
spec:
containers:
- name: podinfo
image: ghcr.io/stefanprodan/podinfo:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9898
env:
- name: PODINFO_UI_COLOR
value: "#34577c"
resources:
limits:
cpu: 2000m
memory: 512Mi
requests:
cpu: 100m
memory: 64Mi
livenessProbe:
httpGet:
path: /healthz
port: 9898
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /readyz
port: 9898
initialDelaySeconds: 5
periodSeconds: 10
3. Golang客户端示例代码
HTTP客户端示例
package main
import (
"context"
"fmt"
"io"
"net/http"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET", "http://podinfo:9898", nil)
if err != nil {
panic(err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Printf("Response: %s\n", body)
}
gRPC客户端示例
package main
import (
"context"
"log"
"time"
pb "github.com/stefanprodan/podinfo/pkg/api/grpc"
"google.golang.org/grpc"
)
func main() {
conn, err := grpc.Dial("podinfo:9999", grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewPodinfoClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.Status(ctx, &pb.StatusRequest{})
if err != nil {
log.Fatalf("could not get status: %v", err)
}
log.Printf("Status: %v", r)
}
4. 配置管理
Podinfo支持通过ConfigMap和环境变量配置:
package main
import (
"log"
"net/http"
"os"
)
type Config struct {
Color string
Message string
ServiceName string
}
func main() {
cfg := Config{
Color: getEnv("PODINFO_UI_COLOR", "#34577c"),
Message: getEnv("PODINFO_UI_MESSAGE", "Welcome to Podinfo"),
ServiceName: getEnv("PODINFO_SERVICE_NAME", "podinfo"),
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(cfg.Message))
})
log.Fatal(http.ListenAndServe(":9898", nil))
}
func getEnv(key, fallback string) string {
if value, ok := os.LookupEnv(key); ok {
return value
}
return fallback
}
5. 健康检查实现
Podinfo的健康检查实现示例:
package main
import (
"net/http"
"sync/atomic"
)
var readiness int32
func main() {
http.HandleFunc("/healthz", healthz)
http.HandleFunc("/readyz", readyz)
http.ListenAndServe(":9898", nil)
}
func healthz(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
}
func readyz(w http.ResponseWriter, r *http.Request) {
if atomic.LoadInt32(&readiness) == 1 {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
} else {
w.WriteHeader(http.StatusServiceUnavailable)
}
}
// 在应用初始化完成后调用
func setReady() {
atomic.StoreInt32(&readiness, 1)
}
6. 指标监控
使用Prometheus客户端库暴露指标:
package main
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
requestsTotal = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Total number of HTTP requests",
},
[]string{"method", "path", "status"},
)
)
func init() {
prometheus.MustRegister(requestsTotal)
}
func main() {
http.Handle("/metrics", promhttp.Handler())
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
requestsTotal.WithLabelValues(r.Method, r.URL.Path, "200").Inc()
w.Write([]byte("Hello World"))
})
http.ListenAndServe(":9898", nil)
}
7. 最佳实践总结
- 资源限制:始终为容器设置资源请求和限制
- 健康检查:实现存活和就绪探针
- 配置分离:使用ConfigMap和Secret管理配置
- 监控:暴露Prometheus格式的指标
- 优雅终止:处理SIGTERM信号实现优雅关闭
- 安全:使用非root用户运行容器
- 日志:输出结构化日志
- 滚动更新:配置适当的更新策略
Podinfo是一个优秀的Kubernetes微服务示例,展示了这些最佳实践的实际应用。通过研究其源代码和部署方式,可以学习到如何在Golang中构建生产就绪的Kubernetes微服务。