resource
k8s
什么是 k8s
开源的容器编排工具
由google开发
帮助在不同的部署环境中管理容器应用
k8s 解决的问题
将传统铁板一块的应用转为微服务管理
增加容器的使用便利
高效管理成千上百的容器的能力
k8s 提供的编排功能
高可用且无关机时延
可扩展性或高性能
容灾,备份和还原
links:
安装
docker runtime 安装 k8s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 yum install -y yum-utils yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin apt-get update apt-get install ca-certificates curl gnupg install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg chmod a+r /etc/apt/keyrings/docker.gpgecho "deb [arch=" $(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ " $(. /etc/os-release && echo "$VERSION_CODENAME " )" stable" | tee /etc/apt/sources.list.d/docker.list > /dev/nullapt update && apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin apt-get update apt-get install ca-certificates curl gnupg install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg chmod a+r /etc/apt/keyrings/docker.gpgecho "deb [arch=" $(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \ " $(. /etc/os-release && echo "$VERSION_CODENAME " )" stable" | tee /etc/apt/sources.list.d/docker.list > /dev/nullapt update && apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin cat >/etc/docker/daemon.json<<EOF { "default-runtime": "nvidia", "exec-opts": [ "native.cgroupdriver=systemd" ], "runtimes": { "nvidia": { "args": [], "path": "nvidia-container-runtime" } }, "builder": { "gc": { "defaultKeepStorage": "20GB", "enabled": true } }, "experimental": true, "features": { "buildkit": true }, "insecure-registries": [ "harbor.baijiayun.com", "docker.huaguisystems.com" ], "registry-mirrors": [ "https://docker.mirrors.sjtug.sjtu.edu.cn", "https://reg-mirror.qiniu.com" ] } EOF systemctl restart docker cat >>/etc/sysctl.d/kubernetes.conf<<EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF sysctl --system cat <<EOF | tee /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF yum updatee && yum install -y kubelet kubeadm kubectl curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | tee -a /etc/apt/sources.list.d/kubernetes.listcurl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add - echo "deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" | tee /etc/apt/sources.list.d/kubernetes.listapt update && apt install -y kubelet kubeadm kubectl swapoff -a setenforce 0 echo 'KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"' | tee -a /etc/default/kubeletsystemctl restart kubelet
配置k8s集群
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 kubeadm config images list kubeadm config images list | xargs docker pull kubeadm init \ --image-repository registry.aliyuncs.com/google_containers \ kubeadm config images pull \ --image-repository registry.aliyuncs.com/google_containers ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtimeapt-get install ntpdate ntpdate cn.pool.ntp.org hwclock --systohc
containerd安装k8s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 swapoff -a cat >>/etc/sysctl.d/kubernetes.conf<<EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF sysctl --system curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | tee -a /etc/apt/sources.list.d/kubernetes.listapt update && apt install -y kubelet kubeadm kubectl containerd config default | tee /etc/containerd/config.toml systemctl restart containerd systemctl status containerd
参考:
QA
kubelet.service failed
1 2 3 4 5 6 7 8 9 10 11 12 kubelet.service - kubelet: The Kubernetes Node Agent Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled) Active: activating (auto-restart) (Result: exit-code) since Wed 2023-07-19 11:44:14 CST; 7s ago Docs: https://kubernetes.io/docs/ Process: 2856971 ExecStart=/usr/bin/kubelet (code=exited, status=1/FAILURE) Main PID: 2856971 (code=exited, status=1/FAILURE) Tasks: 0 Memory: 0B CGroup: /system.slice/kubelet.service Jul 19 11:44:14 localhost.localdomain systemd[1]: Unit kubelet.service entered failed state. Jul 19 11:44:14 localhost.localdomain systemd[1]: kubelet.service failed.
kubelet 启动失败
kubelet服务启动失败。可以通过查看kubelet的日志来获取更多信息,使用以下命令:
1 2 journalctl -fu kubelet journalctl -xe
validate service connection: CRI v1 runtime API is not implemented
错误日志:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@localhost ~]# containerd --version containerd containerd.io 1.6.21 3dce8eb055cbb6872793272b4f20ed16117344f8 [root@localhost ~]# docker info |grep Cgroup Cgroup Driver: cgroupfs WARNING: bridge-nf-call-ip6tables is disabled Cgroup Version: 1 [root@localhost ~]# cat /var/lib/kubelet/kubeadm-flags.env --container-runtime=docker [root@localhost ~]# kubeadm init --pod-network-cidr=10.244.0.0/16 [init] Using Kubernetes version: v1.27.3 [preflight] Running pre-flight checks [WARNING Swap]: swap is enabled; production deployments should disable swap unless testing the NodeSwap feature gate of the kubelet error execution phase preflight: [preflight] Some fatal errors occurred: [ERROR CRI]: container runtime is not running: output: time ="2023-07-19T15:29:19+08:00" level=fatal msg="validate service connection: CRI v1 runtime API is not implemented for endpoint \"unix:///var/run/containerd/containerd.sock\": rpc error: code = Unimplemented desc = unknown service runtime.v1.RuntimeService" , error: exit status 1
解决1: 将containerd配置文件 /etc/containerd/config.toml 的containerd.toml中disabled_plugins = ["cri"]
项注释
[!TIP]
cri 是 Container Runtime Interface 的缩写,这是 Kubernetes 用来与容器运行时进行交互的接口。如果在 containerd.toml 文件中禁用了 cri,那么 containerd 将无法作为 Kubernetes 的容器运行时使用.
解决2: 使用Docker作为其容器运行时。可以通过编辑/etc/default/kubelet文件来完成这个操作。在这个文件中,需要添加或修改以下行:
1 KUBELET_EXTRA_ARGS=--container-runtime=docker
然后,重新启动kubelet服务:
1 systemctl restart kubelet
如何确定k8s运行时
1 kubectl describe nodes | grep 'Container Runtime Version'
基于docker为: Container Runtime Version: docker://24.0.4
基于containerd为: Container Runtime Version: containerd://1.7.1-k3s1
架构
k8s 主要组件
Node & Pod
容器的抽象
Service & Ingress
容器间通信
ConfigMap & Secret
容器运行外部配置
Volume
数据持久化
用于提供数据持久化配置
本地机器,远程或集群外部位置
Deploment & StatefulSet
提供容器副本部署,deployment 下所有配置都由k8s处理
Deploment 提供了多次多节点部署的能力(replica)
Deploment 节点间由svc提供统一访问ip
Deploment 多节点间提供了负载均衡能力
StatefulSet 用于部署状态应用,如 MySQL,MonogDB,ES
StatefulSet 部署 DB 并不容易,通常部署于 k8s 集群外
k8s 配置
kubctl k8s cli
yaml 配置声明模板
etcd 保存了所有的 k8s 组件当前状态
每个配置由3个部分组成 metadata , specification , status
status 由 k8s 从 控制面的 etcd 拉取结果 和 metadata/specification 对比生成
1 2 3 4 5 6 7 8 9 apiVersion: xxx kind: xxx metadata: ... spec: ...
k8s yaml 完整配置
流量请求路径
browser -> (webapp external service) -> webapp(pod) -> (mongodb internal service) -> mongodb(pod)
配置文件:
1 2 3 4 5 6 7 8 9 10 apiVersion: v1 kind: ConfigMap metadata: name: mongo-config data: mongo-url: mongo-service
1 2 3 4 5 6 7 8 9 apiVersion: v1 kind: Secret metadata: name: mongo-secret type: Opaque data: mongo-user: bW9uZ291c2Vy mongo-password: bW9uZ29wYXNzd29yZA==
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 apiVersion: apps/v1 kind: Deployment metadata: name: mongo-deployment labels: app: mongo spec: replicas: 1 selector: matchLabels: app: mongo template: metadata: labels: app: mongo spec: containers: - name: mongodb image: mongo:5.0 ports: - containerPort: 27017 env: - name: MONGO_INITDB_ROOT_USERTNAME valueFrom: secretKeyRef: name: mongo-secret key: mongo-user - name: MONGO_INITDB_ROOT_PASSWORD valueFrom: secretKeyRef: name: mongo-secret key: mongo-password --- apiVersion: v1 kind: Service metadata: name: mongo-service spec: selector: app: mongo ports: - protocol: TCP port: 27017 targetPort: 27017
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 apiVersion: apps/v1 kind: Deployment metadata: name: webapp-deployment labels: app: webapp spec: replicas: 1 selector: matchLabels: app: webapp template: metadata: labels: app: webapp spec: containers: - name: webapp image: nanajanashia/k8s-demo-app:v1.0 ports: - containerPort: 3000 env: - name: USER_NAME valueFrom: name: mongo-secret key: mongo-user - name: USER_PWD valueFrom: name: mongo-secret key: mongo-password - name: DB_URL valueFrom: configMapKeyRef: name: mongo-config key: mongo-url --- apiVersion: v1 kind: Service metadata: name: webapp-service spec: type: NodePort selector: app: webapp ports: - protocol: TCP port: 3000 targetPort: 3000 nodePort: 30100
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 kubectl apply -f mongo-config.yaml kubectl apply -f mongo-secret.yaml kubectl apply -f mongo.yaml kubectl apply -f webapp.yaml kubectl get all kubectl get configmap kubectl get secret kubectl get pod kubectl get --help kubectl describe service webapp-service kubectl describe pod < pod name > kubectl logs < pod name > -f kubectl get svc kubectl get node kubectl get node -o wide
Namespace
提供以名字空间的方式管理资源
每个名字空间需要定义自己的configmap,不同空间通过service访问
default 默认提供的名字空间,默认创建的资源都位于该空间下。
kube-system 不要改动或创建该空间,提供了系统处理,master, kubectl 处理
kube-public 提供了包含集群信息的 configMap 信息
kube-node-lease 提供了感知节点心跳、节点可用
通过 kubectl 创建
1 2 kubectl create namespaec my-ns
通过配置文件创建
1 2 3 4 5 6 7 apiVersioni: v1 kind: ConfigMap metadata: name: mysql-configmap namespace: my-ns data: db_url: mysql-service.database
为什么用 Namespace
结构化管理组件
团队间避免冲突
共享服务
命名空间限制访问及资源
在空间中创建组件
1 2 3 4 kubectl apply -f mysql-configmap.yaml kubectl get configmap kubectl get configmap -n default
Ingress
避免 service ip 及 port 暴露
External Service:通过分配 external IP 给服务(nodePort of ports in Service),使用 ip:port 外部访问
Ingress: 通过分配 routing 规则推动请求到内部服务(internal service),这里http只代表推动请求
Host: 需为合理的域名地址,映射域名地址到节点IP为入口点
配置 Ingress
匹配所有映射规则,可配置单个 domain 映射多服务(多个path)或多 domain 映射规则
管理所有重定向
集群入口控制
大多是由第三方实现,云服务商提供 Ingress 访问(自有虚拟负载均衡)
K8s Nginx Ingress Controller(不需要自己实现)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: dashboard-ingress namespacce: kubernetes-dashboard spec: rules: - host: dashboard.com http: paths: - backend: serviceNamme: kubernetes-dashboard servicePort: 80
1 2 3 4 5 6 kubectl apply -f dashboard-ingress.yaml kubectl get ingress -n kubernetes-dashboard --watch vim /etc/hosts kubectl describe ingress dashboard-ingress -n kubernetes-dashboard
Ingress 常用配置方法
单个 domain 配置多个映射路径
多个 host 配置
https 配置
HPA、KPA
HPA(Horizontal Pod Autoscaler):HPA 是一种Kubernetes控制器,用于根据CPU利用率或自定义指标自动调整Pod的副本数。当Pod的CPU利用率或自定义指标超过或低于一定阈值时,HPA会自动增加或减少Pod的副本数,以确保应用程序的可用性和性能。要使用HPA,需要在Kubernetes集群中启用Metrics Server。
KPA(Kubernetes Pod Autoscaler):KPA 是一种Kubernetes控制器,用于根据内存使用率自动调整Pod的容器资源限制。当Pod的内存使用率超过一定阈值时,KPA会自动增加Pod的容器资源限制,以确保应用程序的可用性和性能。与HPA不同,KPA不会增加或减少Pod的副本数,而是仅调整Pod的容器资源限制。
持久化 in k8s
调度节点
scheduling 。
要将另一台机器加入到当前Kubernetes集群中,需要执行以下步骤:
在要加入集群的机器上安装Kubernetes组件,包括kubelet、kubeadm和kubectl等。
在当前集群中的任意一台机器上运行以下命令,生成加入集群所需的token:
1 kubeadm token create --print-join-command
将第2步生成的加入集群的命令复制到要加入集群的机器上执行。例如:
1 kubeadm join <ip_address>:<port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
其中,ip_address和port是当前Kubernetes集群中某一台机器的地址和端口号,token和hash是第2步生成的。
等待几分钟,新的节点就会加入到集群中,并自动同步集群中的配置信息。
可以使用kubectl命令查看新节点是否已经加入到集群中:
如果新节点已经加入到集群中,那么可以看到它的状态为Ready。
GPU
1 2 kubectl taint nodes --all node-role.kubernetes.io/master-
links:
reference
minikube
minikube 是一个轻量级的 Kubernetes 实现,用于在本地机器上运行单节点 Kubernetes 集群。它支持多个驱动程序(Docker、containerd、cri-o、Podman 等),可以在 Linux、macOS 和 Windows 上运行。
安装
1 2 curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 sudo install minikube-linux-amd64 /usr/local/bin/minikube
[!TIP] 常见错误
memory-swap is not allowed
若在 docker 中使用minikube,则需要为 docker 容器开启 privileged 权限。
基本使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 minikube start --driver=docker [--memory=2g] [--kubernetes-version=1.22.1] minikube stop minikube delete minikube kubectl -- api-versions kubectl api-versions minikube status minikube ip minikube version minikube addons enable metrics-server minikube dashboard kubectl proxy http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/
运行应用
1 2 3 4 5 6 7 8 9 10 11 kubectl create deployment hello-minikube --image=k8s.gcr.io/echoserver:1.4 kubectl expose deployment hello-minikube --type =NodePort --port=8080 kubectl get services minikube service hello-minikube
本地多集群模拟
在minikube中,如果需要创建多个本地集群,可以使用以下步骤:
使用不同的文件夹或文件名安装多个minikube实例。例如,可以使用以下命令安装两个minikube实例:
1 2 3 4 minikube start -p cluster-1 minikube start -p cluster-2 minikube profile list
在使用多个minikube实例时,需要使用minikube profile
命令来设置当前使用的minikube实例。例如,要使用cluster-1
实例,可以使用以下命令:
1 minikube profile cluster-1
然后,可以使用kubectl
命令与该实例进行交互。
如果不再需要某个minikube实例,可以使用以下命令删除它:
1 minikube delete -p cluster-1
这将删除名为cluster-1
的minikube实例。
kind
使用 kind 创建本地 cluster。
安装完成后,可以使用 kind 来管理 Kubernetes 集群。一些常用的命令包括:
kind create cluster: 创建一个新的 Kubernetes 集群
kind delete cluster: 删除当前的 Kubernetes 集群
kind get clusters: 获取当前存在的 Kubernetes 集群
kind load docker-image: 将本地的 Docker 镜像加载到 kind 集群中
kind export kubeconfig: 将 kind 集群的 kubeconfig 导出到本地文件中
kind get nodes: 获取 kind 集群中的节点
gpu support
links:
kubectl
kubectl 是 Kubernetes 的命令行工具,用于管理 Kubernetes 集群,C/S 架构。
安装
1 2 3 4 5 6 7 curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt) /bin/linux/amd64/kubectl" chmod +x kubectlsudo mv kubectl /usr/local/bin/kubectl version --client kubectl version --client --output=yaml
1 choco install kubernetes-cli
基本使用
k8s cli 工具 kubectl,提供了操作基本组件及交互能力。
create/edit/delete deployment:基于 deployment 的 CRUD 操作
get nodes/pod/service/replicaset/deployment: 查看 k8s 不同组件状态
logs [pod name]: 调试 pod
exec -it [pod name] – bash: 获取交互式终端
describe pod [pod name]: 获取 pod 详情
apply -f [file name]: 应用配置
delete -f [file name]: 删除配置
deployment 管理 replicaset
replicaset 管理 pod
pod 是容器的抽象
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 kubectl api-version kubectl cluster-info kubectl get [subcommand] kubectl describe pod [name] kubectl apply -f [file] kubectl delete pod [pod-name] kubectl delete pods -l <label> -n <namespace>
持久化存储
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 kubectl apply -f https://k8s.io/examples/pods/storage/pv-claim.yaml kubectl apply -f https://k8s.io/examples/pods/storage/pv-pod.yaml kubectl get pod task-pv-pod kubectl exec -it task-pv-pod -- /bin/bash echo "Hello World" > /usr/share/nginx/html/index.htmlexit kubectl delete pod task-pv-pod kubectl apply -f https://k8s.io/examples/pods/storage/pv-pod.yaml kubectl get pod task-pv-pod kubectl exec -it task-pv-pod -- /bin/bash cat /usr/share/nginx/html/index.htmlexit kubectl delete pvc task-pv-claim
pod 调试
查看及调试 pod 详情,k8s官方 POD 调试参考 。
1 2 3 4 5 6 7 8 9 kubectl create deployment nginx-depl --image=nginx kubectl edit deployment nginx-depl kubectl delete deployment nginx-depl kubectl rollout status [pod-name]
1 2 3 4 5 6 7 8 9 kubectl create deployment mongo-depl --image=mongo kubectl get pod kubectl describe pod mongo-depl-xxxx kubectl logs mongo-depl-xxxx kubectl exec -it mongo-depl-xxxx -- bash
k3d
gpu workload
links:
kustomize
kustomize 是一个用于Kubernetes部署的工具,它允许通过声明性配置来管理应用程序的部署。使用Kustomize,可以轻松地管理多个环境(如开发、测试和生产)之间的差异,而无需为每个环境创建单独的部署文件。
Kustomize使用Kubernetes的原生API来管理部署,因此它与Kubernetes的其他工具(如kubectl)非常兼容。此外,Kustomize还支持使用变量和模板来生成部署文件,使得管理大型应用程序变得更加容易。详情文档参考 。
安装
1 curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
helm
概念
helm 是 k8s 包管理 yaml 工具。
helm charts
一堆 yaml 文件
使用 helm 创建自己的 charts
推送 chars 到 helm 仓库
使用现有的 helm chars
使用模板引擎配置 yaml
helm char 结构
links:
安装
1 2 3 4 5 6 7 8 9 10 wget -o helm.tar.gz https://storage.googleapis.com/kubernetes-helm/helm-v2.13.1-linux-amd64.tar.gz tar -zxvf helm.tar.gz curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash wget -o helm.tar.gz https://mirrors.huaweicloud.com/helm/v3.12.2/helm-v3.12.2-linux-amd64.tar.gz tar -zxvf helm.tar.gz cp linux-amd64/helm /usr/local/bin/
links:
基本使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 helm repo add bitnami https://charts.bitnami.com/bitnami helm repo add brigade https://brigadecore.github.io/charts helm repo update helm install --values=my-values.yaml <charname> helm install --set version=v2.0.0 helm upgrade -i nvdp nvdp/nvidia-device-plugin \ --namespace nvdp \ --create-namespace \ --set =runtimeClassName=nvidia \ --set =image.repository=registry.gitlab.com/nvidia/kubernetes/device-plugin/staging/k8s-device-plugin \ --set =image.tag=8b416016 helm uninstall nvdp
打包
helm create --generate-from-existing` 是 Helm 命令行工具中的一个命令,用于从现有的 Kubernetes 资源中生成 Helm 包的模板。
它的语法是:
1 helm create <chart-name> --generate-from-existing <existing-resource>
其中,<chart-name>
是 Helm 包的名称,<existing-resource>
是现有的 Kubernetes 资源名称。
该命令将会从现有的 Kubernetes 资源中生成 Helm 包的模板,包括 Chart.yaml
、values.yaml
和 templates
目录等文件。在生成的 Helm 包模板中,所有的 Kubernetes 资源将会被转换为 Helm 模板语法。
例如,假设我们有一个名为 my-app
的 Kubernetes 资源,我们可以使用以下命令生成一个 Helm 包模板:
1 helm create my-chart --generate-from-existing my-app
这将会在当前目录下生成一个名为 my-chart
的 Helm 包模板,其中包括 Chart.yaml
、values.yaml
和 templates
目录等文件,所有的 Kubernetes 资源都会被转换为 Helm 模板语法。
需要注意的是,该命令只能生成基本的 Helm 包模板,仍然需要手动编辑以适应特定的需求。此外,该命令仅适用于 Kubernetes 资源,不适用于其他类型的资源。
rancher
rancher 是一个 全栈式 的 Kubernetes 容器管理平台,为提供在任何地方都能成功运行 Kubernetes 的工具。
links:
安装
单节点通过容器安装,并访问浏览器访问 ip:443,设置 admin 密码, 右下角可设置显示语言为简体中文。
1 2 3 4 5 docker run -d --restart=unless-stopped \ --name rancher \ -p 80:80 -p 443:443 \ --privileged \ rancher/rancher:v2.5.9
参考:
App
gpu
rke
Rancher Kubernetes Engine,简称 RKE,是一个经过 CNCF 认证的 Kubernetes 安装程序。
links:
k3s
K3s 是一个轻量级的 Kubernetes 发行版,它针对边缘计算、物联网等场景进行了高度优化。
links:
安装
Quickstart
使用脚本部署快速部署
1 2 3 4 5 curl -sfL https://get.k3s.io | sh - curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh - k3s-uninstall.sh
运行此安装后,详情参考 :
K3s 服务将被配置为在节点重启后或进程崩溃或被杀死时自动重启.
将安装其他实用程序,包括 kubectl, crictl, ctr, k3s-killall.sh 和 k3s-uninstall.sh
将kubeconfig文件写入到/etc/rancher/k3s/k3s.yaml
,由 K3s 安装的 kubectl 将自动使用该文件.
1 2 3 systemctl status k3s journalctl -u k3s
Run with autok3s
AutoK3s 是用于简化 K3s 集群管理的轻量级工具,可以使用 AutoK3s 在任何地方运行 K3s 服务。
1 2 3 4 docker run -itd --name autok3s \ --restart=unless-stopped \ -p 8080:8080 \ cnrancher/autok3s:v0.6.0
Run k3s in docker
在容器中运行k3s集群, 镜像由 rancher 社区提供
1 2 3 4 5 6 7 docker run \ --privileged \ --name k3s-server-1 \ --hostname k3s-server-1 \ -p 6443:6443 \ -d rancher/k3s:v1.24.10-k3s1 \ server
运行起来后,通过kubeconfig进行访问
1 docker cp k3s-server-1:/etc/rancher/k3s/k3s.yaml ~/.kube/config
[!TIP]
如果需要gpu支持的 k3s 运行在容器中时, 需要安装cuda及做相关配置
links:
Run k3s Based on docker
k3s默认使用自己维护的 /var/lib/rancher/rke2/bin/containerd
作为运行时. 以docker作为运行时需要指定参数: -s - --docker
.
1 2 3 curl -sfL https://get.k3s.io | sh -s - --docker curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_RKE2_MIRROR=cn sh -s - --docker
[!TIP]
可以将k3s配置到使用docker的运行时,方便资源管理
links:
Run k3s Based on containerd
k3s默认使用自己维护的 /var/lib/rancher/rke2/bin/containerd
作为运行时, 如果需要用自定义的 containerd时,需指定参数 -s - --container-runtime-endpoint /run/containerd/containerd.sock
1 2 3 4 5 6 curl -sfL https://get.k3s.io | sh - curl -sfL https://get.k3s.io | sh -s - --container-runtime-endpoint /run/containerd/containerd.sock curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_RKE2_MIRROR=cn sh -s - --container-runtime-endpoint /run/containerd/containerd.sock
[!TIP]
同时也可以将docker配置为使用自定义的containerd,方便资源管理
编辑Docker的daemon.json文件(通常位于/etc/docker/daemon.json),添加以下内容, 然后重启docker服务systemctl restart docker
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 { "exec-opts" : [ "native.cgroupdriver=systemd" ] , "log-driver" : "json-file" , "log-opts" : { "max-size" : "100m" } , "storage-driver" : "overlay2" , "containerd" : "/run/containerd/containerd.sock" }
这样,k3s和Docker就会使用同一个containerd实例作为其容器运行时, 在不考虑docker时优先使用containerd。
QA
1 2 umount $(df -HT | grep '/var/lib/kubelet' | awk '{print $7}' )
访问集群
存储在 /etc/rancher/k3s/k3s.yaml
的是部署的k3集群的 kubeconfig 文件, 用于对 Kubernetes 集群的访问
1 2 3 export KUBECONFIG=/etc/rancher/k3s/k3s.yamlkubectl get pods --all-namespaces helm ls --all-namespaces
直接指定 kubeconfig
1 2 kubectl --kubeconfig /etc/rancher/k3s/k3s.yaml get pods --all-namespaces helm --kubeconfig /etc/rancher/k3s/k3s.yaml ls --all-namespaces
links:
gpu on k3s
Step 1, 准备节点(驱动等)
Step 2, 安装 k8s nvidia plugins
Step 3, benchmark测试
links:
Based on docker
根据k3s文档 ,注册 RuntimeClass及nvidia设备发现及调度插件.
1 2 3 4 5 6 7 8 apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: nvidia handler: docker ---
links:
Based on containerd
根据k3s文档 ,注册 RuntimeClass及nvidia设备发现及调度插件.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: nvidia handler: nvidia --- apiVersion: v1 kind: Namespace metadata: name: node-feature-discovery --- apiVersion: v1 kind: ServiceAccount metadata: name: nfd-master namespace: node-feature-discovery --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: nfd-master rules: - apiGroups: - "" resources: - nodes verbs: - get - patch - update --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: nfd-master roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: nfd-master subjects: - kind: ServiceAccount name: nfd-master namespace: node-feature-discovery --- apiVersion: apps/v1 kind: DaemonSet metadata: labels: app: nfd name: nfd namespace: node-feature-discovery spec: selector: matchLabels: app: nfd template: metadata: labels: app: nfd spec: serviceAccount: nfd-master runtimeClassName: nvidia containers: - env: - name: NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName image: quay.io/kubernetes_incubator/node-feature-discovery:v0.6.0 name: nfd-master command: - "nfd-master" args: - "--extra-label-ns=nvidia.com" - env: - name: NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName image: quay.io/kubernetes_incubator/node-feature-discovery:v0.6.0 name: nfd-worker command: - "nfd-worker" args: - "--sleep-interval=60s" - "--options={\"sources\": {\"pci\": { \"deviceLabelFields\": [\"vendor\"] }}}" volumeMounts: - name: host-boot mountPath: "/host-boot" readOnly: true - name: host-os-release mountPath: "/host-etc/os-release" readOnly: true - name: host-sys mountPath: "/host-sys" - name: source-d mountPath: "/etc/kubernetes/node-feature-discovery/source.d/" - name: features-d mountPath: "/etc/kubernetes/node-feature-discovery/features.d/" volumes: - name: host-boot hostPath: path: "/boot" - name: host-os-release hostPath: path: "/etc/os-release" - name: host-sys hostPath: path: "/sys" - name: source-d hostPath: path: "/etc/kubernetes/node-feature-discovery/source.d/" - name: features-d hostPath: path: "/etc/kubernetes/node-feature-discovery/features.d/" --- apiVersion: apps/v1 kind: DaemonSet metadata: name: gpu-feature-discovery namespace: node-feature-discovery labels: app.kubernetes.io/name: gpu-feature-discovery app.kubernetes.io/version: 0.6 .1 app.kubernetes.io/part-of: nvidia-gpu spec: selector: matchLabels: app.kubernetes.io/name: gpu-feature-discovery app.kubernetes.io/part-of: nvidia-gpu template: metadata: labels: app.kubernetes.io/name: gpu-feature-discovery app.kubernetes.io/version: 0.6 .1 app.kubernetes.io/part-of: nvidia-gpu spec: runtimeClassName: nvidia containers: - image: nvcr.io/nvidia/gpu-feature-discovery:v0.6.1 name: gpu-feature-discovery volumeMounts: - name: output-dir mountPath: "/etc/kubernetes/node-feature-discovery/features.d" - name: dmi-product-name mountPath: "/sys/class/dmi/id/product_name" securityContext: privileged: true env: - name: MIG_STRATEGY value: none nodeSelector: feature.node.kubernetes.io/pci-10de.present: "true" volumes: - name: output-dir hostPath: path: "/etc/kubernetes/node-feature-discovery/features.d" - name: dmi-product-name hostPath: path: "/sys/class/dmi/id/product_name" --- apiVersion: apps/v1 kind: DaemonSet metadata: name: nvidia-device-plugin-daemonset namespace: kube-system spec: selector: matchLabels: name: nvidia-device-plugin-ds updateStrategy: type: RollingUpdate template: metadata: labels: name: nvidia-device-plugin-ds spec: tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule priorityClassName: "system-node-critical" runtimeClassName: "nvidia" containers: - image: nvcr.io/nvidia/k8s-device-plugin:v0.14.1 name: nvidia-device-plugin-ctr env: - name: FAIL_ON_INIT_ERROR value: "false" securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL" ] volumeMounts: - name: device-plugin mountPath: /var/lib/kubelet/device-plugins volumes: - name: device-plugin hostPath: path: /var/lib/kubelet/device-plugins --- apiVersion: v1 kind: Pod metadata: name: cuda-sample-vectoradd namespace: default spec: restartPolicy: OnFailure runtimeClassName: nvidia containers: - name: cuda-container image: nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda10.2 resources: limits: nvidia.com/gpu: 1 env: - name: NVIDIA_VISIBLE_DEVICES value: all - name: NVIDIA_DRIVER_CAPABILITIES value: all
Enable with helm
根据上面两种方式, 需设置 runtimeClassName, 在使用 helm 安装 k8s-device-plugin 步骤如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 cat <<EOF | kubectl apply -f - apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: nvidia handler: nvidia # 创建基于 containerd 的RuntimeClass, 使用dockerd时改为docker EOF helm repo add nvdp https://nvidia.github.io/k8s-device-plugin helm upgrade -i nvdp nvdp/nvidia-device-plugin \ --namespace nvdp \ --create-namespace \ --set =runtimeClassName=nvidia \ --set =image.repository=registry.gitlab.com/nvidia/kubernetes/device-plugin/staging/k8s-device-plugin \ --set =image.tag=8b416016 helm upgrade -i nvdp nvdp/nvidia-device-plugin \ --namespace nvdp \ --create-namespace \ --version v0.14.1 \ --set =runtimeClassName=nvidia \ --set =image.repository=nvcr.io/nvidia/k8s-device-plugin
links:
Test
测试 cuda sample.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: gpu-pod spec: restartPolicy: Never runtimeClassName: nvidia containers: - name: cuda-container image: nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda10.2 resources: limits: nvidia.com/gpu: 1 # requesting 1 GPU tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule EOF
links:
k3s registry mirror
如果从国内环境安装 K3s 可能会遇到安装速度特别缓慢或者 time out 的情况,从以上的安装过程可以分析出主要由以下几个原因导致:
配置国内镜像
1 2 3 4 5 6 7 8 9 10 cat <<EOF > /etc/rancher/k3s/registries.yaml mirrors: "docker.io": endpoint: - "https://docker.mirrors.ustc.edu.cn" # 可根据需求替换 mirror 站点 - "https://registry-1.docker.io" EOF systemctl restart k3s crictl info
经过以上配置后,通过 K3s 拉取的镜像如果在配置的 mirror 站点中存在,那么将会从该站点拉取镜像。如果不存在,将会从默认的 docker.io 中拉取镜像。
links:
traefik
默认情况下,K3s 1.21 及更高版本默认安装 Traefik v2。出于安全考虑,默认不公开 Traefik Dashboard。参考
links:
crictl
crictl
是一个用于与 Kubernetes 中的容器运行时接口 (CRI) 进行交互的命令行工具。它允许在 Kubernetes 集群中管理容器和 Pod。它提供了创建、列出、启动、停止和删除容器等功能。
基本使用
1 2 3 4 5 6 crictl info crictl images crictl pods
–runtime-endpoint
1 2 3 4 5 6 7 8 export CONTAINER_RUNTIME_ENDPOINT=unix:///run/containerd/containerd.sockecho 'runtime-endpoint: unix:///run/containerd/containerd.sock' >> /etc/crictl.yamlcrictl --runtime-endpoint unix:///run/containerd/containerd.sock info
rke2
rke2 ,也被称为 RKE Government,是 Rancher 的下一代 Kubernetes 发行版
links:
安装
1 2 3 curl -sfL https://get.rke2.io | sh - curl -sfL https://rancher-mirror.rancher.cn/rke2/install.sh | INSTALL_RKE2_MIRROR=cn sh -
links:
istio
解析微服务实践中网络稳定的痛点,实践中通常使用服务网格 Service Mesh 。
Service Mesh 演化
代码逻辑处理网络可靠,难维护
公共库,解决耦合
代理,功能简陋
Sidecar
Service Mesh
Service Mesh V2(加了控制平面)
Service Mesh
[!NOTE]
A service mesh is a dedicated infrastructure layer for handling service-to-service communication. It’s responsible for the reliable delivery of requests through the complex topology of services that comprise a modern,cloud native application. In practice,the service mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code,without the application needing to be aware .
服务网格是用于处理服务到服务通信的专用基础设施层。它负责通过组成现代云原生应用程序的复杂服务拓扑可靠地交付请求。在实践中,服务网格通常被实现为一组轻量级网络代理,它们与应用程序代码一起部署,而不需要应用程序察觉。即,应用中服务会有额外的Sidecar服务代理请求并可靠的提供通信的网络拓扑。
Service Mesh 标准:
istio
istio 定义
服务网格产品
对应用层透平
为微服务架构设计
可连接、保护、控制遥测系统
istio 核心资源 CRD
虚拟服务(Virtual Service)
将流量路由给定目标规则
请求地址和真实工作负载解耦
包含一组路由规则
丰富的路由匹配规则
目标规则(Destination Rule)
定义虚拟服务路由到目标真实地址,即子集
负载均衡,随机、权重、最小请求数
Sidecar
调整 Envoy 代理接管的端口和协议
限制 Envoy 代理可访问的服务
可观测性
指标(Metrics)
以聚合方式监控和理解系统行为
istio 中指标的分类
代理级别指标(Proxy-level)
服务级别指标(Service-level)
控制平面指标(Control plane)
日志(Logging)
系统产生事件了解系统
包含完整的元数据信息(目标、源)
生成位置可选(本地、远端,如filebeat)
日志内容
应用日志
Envoy 日志 kubectl logs -l app=demo -c istio-proxy
追踪(Tracing)
安全架构
认证
授权
安装
配置安装 istio 。
[!NOTE]
istio 需要匹配k8s环境。
curl -L https://istio.io/downloadIstio | sh -
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 istioctl version istioctl manifest apply istioctl manifest apply --set profile=demo istioctl manifest apply --set addonComponents.grafana.enable=true kubectl get ns kubectl get pod -n istio-system kubectl get crd | grep istio kubectl api-resources | grep istio istioctl dashboard kiali kubectl label namespace default istio-injection=enabled
[!TIP]
可以部署 Bookinfo 应用,验证istio。
示例部署 Bookinfo,并使用默认的 gateway 配置 ingressgateway,然后导出 8099 给外部访问。
1 2 3 4 kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml kubectl port-forward svc/istio-ingressgateway 8099:80 -n istio-system curl localhost:8099/productpage
Virtucal Service 和 Destination Rule
可实现的功能:
按服务版本路由
将流量都路由到v1,samples/bookinfo/networking/virtual-service-all-v1.yaml
按比例流量区分
根据匹配规则进行路由
根据请求url前缀匹配,samples/bookinfo/networking/bookinfo-gateway.yaml
定义各种策略(负载均衡、连接池等)
knative
[!NOTE]
knative is an Open-Source Enterprise-level solution to build Serverless and Event Driven Applications.
Knative是一个企业级的开源软件构建无服务器和事件驱动应用程序的解决方案。
knative 文档
要了解如何在Kubernetes上使用Knative,需要重点关注以下文档:
Knative官方文档中的以下章节对于了解Knative也非常重要:
traefik
Traefik是一种流行的反向代理和负载均衡器,可用于将流量路由到不同的后端服务。它支持多种后端服务,例如Docker,Kubernetes和Consul等。Traefik还提供了许多有用的功能,例如自动发现和自动配置。
参考:
traefik 示例
docker-compose 示例
如果正在使用Docker,则可以使用Traefik作为反向代理和负载均衡器。Traefik可以自动发现Docker容器,并将流量路由到正确的容器。以下是一个示例docker-compose文件,其中包含Traefik和一个Web服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 version: '3' services: traefik: image: traefik:v2.4 command: - "--api.insecure=true" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" ports: - "80:80" - "8080:8080" volumes: - "/var/run/docker.sock:/var/run/docker.sock" web: image: nginx:alpine labels: - "traefik.enable=true" - "traefik.http.routers.web.rule=Host(`web.example.com`)" - "traefik.http.services.web.loadbalancer.server.port=80"
在此示例中,Traefik将监听端口80,并将流量路由到Web服务。Web服务使用Traefik标签来指示Traefik应该将其作为后端服务使用。Traefik还使用标签来指定路由规则。
k8s 示例
在Kubernetes中,Traefik可以使用Kubernetes Ingress对象来路由流量。
要在Kubernetes中使用Traefik,请按照以下步骤操作:
安装Traefik Operator,Traefik Operator是一个Kubernetes控制器,用于管理Traefik实例。可以使用Helm Chart安装Traefik Operator。以下是安装Traefik Operator的命令:
1 2 3 helm repo add traefik https://helm.traefik.io/traefik helm repo update helm install traefik-operator traefik/traefik-operator
创建Traefik实例,要在Kubernetes中使用Traefik,需要创建一个Traefik实例。可以使用Traefik CRD(Custom Resource Definition)来定义Traefik实例。以下是一个示例Traefik CRD:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 apiVersion: traefik.containo.us/v1alpha1 kind: TraefikService metadata: name: traefik spec: ports: - name: http port: 80 - name: admin port: 8080 api: dashboard: true entryPoints: - name: http address: ":80" - name: https address: ":443"
在此示例中,Traefik将监听端口80和8080,并将流量路由到正确的后端服务。Traefik还将启用Traefik Dashboard,并监听端口8080。
要创建Traefik实例,请使用以下命令:
1 kubectl apply -f traefik-crd.yaml
创建网关,网关可以使用 k8s 网关或 traefik IngressRoute。
要在Kubernetes中使用Traefik路由流量,需要创建一个Ingress对象。以下是一个示例Ingress对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: web annotations: traefik.ingress.kubernetes.io/router.entrypoints: http traefik.ingress.kubernetes.io/router.rule: "Host(`example.com`)" spec: rules: - host: example.com http: paths: - path: / pathType: Prefix backend: service: name: web port: name: http
在此示例中,Ingress对象将流量路由到名为“web”的Kubernetes Service。Traefik将使用标签“traefik.ingress.kubernetes.io/router.rule”来指定路由规则。
要创建Ingress对象,请使用以下命令:
1 kubectl apply -f ingress.yaml
在Kubernetes上使用Traefik的信息,并且想要了解如何使用Traefik IngressRoute。Traefik IngressRoute是Traefik的一种扩展,它提供了更多的路由选项和更好的可读性。要在Kubernetes中使用Traefik IngressRoute路由流量,需要创建一个IngressRoute对象。以下是一个示例IngressRoute对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: web spec: entryPoints: - web routes: - match: Host(`example.com`) && PathPrefix(`/web`) kind: Rule services: - name: web port: 80
在此示例中,IngressRoute对象将流量路由到名为“web”的Kubernetes Service。Traefik将使用标签“match”来指定路由规则。
要创建IngressRoute对象,请使用以下命令:
1 kubectl apply -f ingressroute.yaml
[!NOTE]
Traefik和Istio是两个不同的工具,它们都可以用于在Kubernetes中管理流量路由和负载均衡,但它们的设计目标和功能略有不同。
Traefik是一个轻量级的反向代理和负载均衡器,它专注于将流量路由到正确的后端服务。Traefik提供了许多路由选项和可插拔的中间件,例如TLS证书管理和HTTP重定向。Traefik还提供了一个易于使用的Web UI,用于监视和管理流量路由。
相比之下,Istio是一个更全面的服务网格解决方案,它提供了更多的功能,例如流量管理、安全性和可观察性。Istio使用Envoy作为其数据平面,Envoy是一个高性能的代理,它可以在应用程序和服务之间进行流量路由和负载均衡。Istio还提供了一些高级功能,例如流量控制、故障注入和跟踪。
因此,如果只需要一个简单的反向代理和负载均衡器,Traefik可能是更好的选择。但是,如果需要更全面的服务网格功能,例如流量管理和安全性,那么Istio可能更适合需求。
opentelemetry
opentelemetry 是一个api、sdk和工具的集合。使用它来检测、生成、收集和导出遥测数据(度量、日志和跟踪),以帮助分析软件的性能和行为。