
2gis/k8s-handlek8s-handle 是一个命令行工具,用于简化 Kubernetes 应用的持续交付流程。它支持多环境配置,可使用相同的部署模板部署到不同环境(如 staging 和 production),是 Helm 的替代方案,但不包含包管理器功能。
kubectl(如未安装)[***]bash$ cat > ~/.kube/kubernetes.ca.crt << EOF > <粘贴集群 CA 证书内容> >EOF cat > ~/.kube/config << EOF apiVersion: v1 kind: Config preferences: {} clusters: - cluster: certificate-authority: kubernetes.ca.crt server: <protocol://masterurl:port> name: my-cluster contexts: - context: cluster: my-cluster namespace: my-namespace user: my-user name: my-context current-context: my-context users: - name: my-user user: token: <你的 token> EOF
需 Python 3.4 或更高版本:
bash$ pip install k8s-handle -- 或 -- $ pip install --user k8s-handle
bash$ cd $WORKDIR $ git clone [***] $ cd k8s-handle-example $ docker run --rm -v $(pwd):/tmp/ -v "$HOME/.kube:/root/.kube" 2gis/k8s-handle k8s-handle deploy -s staging --use-kubeconfig INFO:templating:File "/tmp/k8s-handle/configmap.yaml" successfully generated INFO:templating:Trying to generate file from template "secret.yaml.j2" in "/tmp/k8s-handle" INFO:templating:File "/tmp/k8s-handle/secret.yaml" successfully generated INFO:templating:Trying to generate file from template "deployment.yaml.j2" in "/tmp/k8s-handle" INFO:templating:File "/tmp/k8s-handle/deployment.yaml" successfully generated INFO:k8s.resource:ConfigMap "k8s-starter-kit-nginx-conf" already exists, replace it INFO:k8s.resource:Secret "k8s-starter-kit-secret" already exists, replace it INFO:k8s.resource:Deployment "k8s-starter-kit" does not exist, create it _(_)_ wWWWw _ @@@@ (_)@(_) vVVVv _ @@@@ (___) _(_)_ @@()@@ wWWWw (_)\ (___) _(_)_ @@()@@ Y (_)@(_) @@@@ (___) `|/ Y (_)@(_) @@@@ \|/ (_) / Y \| \|/ /(_) \| |/ | \ | \ |/ | / \ | / \|/ |/ \| \|/ \|// \|/// \|// \|/// \|/// \|// |// \|// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
如果使用 Gitlab CI、TeamCity 等工具,可通过 Docker 运行器/代理集成,脚本略有不同:
bash$ k8s-handle deploy -s staging
需 checkout 代码仓库 [***] 并切换到分支 without-kubeconfig,同时设置以下环境变量:
使用镜像 2gis/k8s-handle:<版本号或 latest>
注意:如果使用 Gitlab CI,可配置 Kubernetes 集成,直接使用 --use-kubeconfig 标志。
bash$ k8s-handle deploy -s staging --use-kubeconfig INFO:templating:Trying to generate file from template "configmap.yaml.j2" in "/tmp/k8s-handle" INFO:templating:File "/tmp/k8s-handle/configmap.yaml" successfully generated INFO:templating:Trying to generate file from template "secret.yaml.j2" in "/tmp/k8s-handle" INFO:templating:File "/tmp/k8s-handle/secret.yaml" successfully generated INFO:templating:Trying to generate file from template "deployment.yaml.j2" in "/tmp/k8s-handle" INFO:templating:File "/tmp/k8s-handle/deployment.yaml" successfully generated INFO:k8s.resource:ConfigMap "k8s-starter-kit-nginx-conf" already exists, replace it INFO:k8s.resource:Secret "k8s-starter-kit-secret" already exists, replace it INFO:k8s.resource:Deployment "k8s-starter-kit" does not exist, create it _(_)_ wWWWw _ @@@@ (_)@(_) vVVVv _ @@@@ (___) _(_)_ @@()@@ wWWWw (_)\ (___) _(_)_ @@()@@ Y (_)@(_) @@@@ (___) `|/ Y (_)@(_) @@@@ \|/ (_) / Y \| \|/ /(_) \| |/ | \ | \ |/ | / \ | / \|/ |/ \| \|/ \|// \|/// \|// \|/// \|/// \|// |// \|// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ $ kubectl get configmap NAME DATA AGE k8s-starter-kit-nginx-conf 1 1m $ kubectl get secret | grep starter-kit k8s-starter-kit-secret Opaque 1 1m $ kubectl get deploy NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE k8s-starter-kit 1 1 1 1 3m
修改 config.yaml 中 replicas_count 为 3,使用同步模式重新运行:
bash$ k8s-handle deploy -s staging --use-kubeconfig --sync-mode ... INFO:k8s.resource:Deployment "k8s-starter-kit" already exists, replace it INFO:k8s.resource:desiredReplicas = 3, updatedReplicas = 3, availableReplicas = 1 INFO:k8s.resource:Deployment not completed on 1 attempt, next attempt in 5 sec. INFO:k8s.resource:desiredReplicas = 3, updatedReplicas = 3, availableReplicas = 2 INFO:k8s.resource:Deployment not completed on 2 attempt, next attempt in 5 sec. INFO:k8s.resource:desiredReplicas = 3, updatedReplicas = 3, availableReplicas = 3 INFO:k8s.resource:Deployment completed on 3 attempt ... $ kubectl get deploy NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE k8s-starter-kit 3 3 3 3 7m
可通过示例仓库快速开始:[***] Nginx 应用及所需的 Kubernetes 资源配置。
bash$ cd $WORKDIR $ git clone [***] $ cd k8s-handle-example $ k8s-handle deploy -s staging --use-kubeconfig --sync-mode INFO:__main__:Using default namespace k8s-handle-test INFO:templating:Trying to generate file from template "configmap.yaml.j2" in "/tmp/k8s-handle" INFO:templating:File "/tmp/k8s-handle/configmap.yaml" successfully generated INFO:templating:Trying to generate file from template "deployment.yaml.j2" in "/tmp/k8s-handle" INFO:templating:File "/tmp/k8s-handle/deployment.yaml" successfully generated INFO:templating:Trying to generate file from template "service.yaml.j2" in "/tmp/k8s-handle" INFO:templating:File "/tmp/k8s-handle/service.yaml" successfully generated INFO:k8s.resource:ConfigMap "example-nginx-conf" does not exist, create it INFO:k8s.resource:Deployment "example" does not exist, create it INFO:k8s.resource:desiredReplicas = 1, updatedReplicas = 1, availableReplicas = None INFO:k8s.resource:Deployment not completed on 1 attempt, next attempt in 5 sec. INFO:k8s.resource:desiredReplicas = 1, updatedReplicas = 1, availableReplicas = None INFO:k8s.resource:Deployment not completed on 2 attempt, next attempt in 5 sec. INFO:k8s.resource:desiredReplicas = 1, updatedReplicas = 1, availableReplicas = 1 INFO:k8s.resource:Deployment completed on 3 attempt INFO:k8s.resource:Service "example" does not exist, create it $ kubectl -n k8s-handle-test get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE example NodePort 10.100.132.168 <none> 80:31153/TCP 52s $ curl http://<任意节点IP>:31153 <h1>Hello world!</h1> Deployed with k8s-handle.
k8s-handle 工作依赖两个组件:
-c 参数指定的其他 YAML 文件):存储所有部署配置如果有测试、预发、生产等多环境,可通过一套模板覆盖所有环境,无需重复配置。
Common 部分定义所有环境共享的变量:
yamlcommon: app_name: my-shiny-app app_port: 8080
这些变量会与指定环境的变量合并。Common 部分为可选。
定义具体环境的变量:
yamltesting: replicas: 1 request_cpu: 100m request_memory: 128M some_option: disabled
测试环境通常资源需求较低,副本数为 1。
yamlstaging: replicas: 2 request_cpu: 200m request_memory: 512M
预发环境用于集成测试和演示,可适当提高副本数和资源。
yamlproduction-zone-1: replicas: 50 request_cpu: 1000m request_memory: 1G production: "true" never_give_up: "true"
生产环境需处理高并发,设置高副本数和资源,并配置生产特定变量。
在 CI/CD 脚本中部署指定环境:
bash$ k8s-handle deploy -s staging # 或 testing、production-zone-1
例如在 Gitlab CI 中,可为每个环境创建手动触发任务。
模板使用 Jinja2 语法,支持标准过滤器及以下特殊过滤器:
{{ my_var | b64encode }} - 将 my_var 的值编码为 base64{{ my_var | b64decode }} - 将 my_var 的值从 base64 解码{{ my_var | hash_sha256 }} - 将 my_var 的值编码为 sha256 哈希{{ my_var | to_yaml(flow_style=True, width=99999) }} - 将变量渲染为 YAML 格式(flow_style=True 为单行,False 为多行;width 为最大行宽)注意:过滤器仅用于模板,不可用于 config.yaml
{{ include_file('my_file.txt') }} - 导入 my_file.txt 内容(不解析),适用于将配置文件导入 ConfigMap。文件路径相对于模板目录的父目录(通常为项目根目录):bash$ ls -1 config.yaml templates my_file.txt ...
{{ list_files('dir/or/glob*') }} - 返回指定目录下的文件列表,适用于导入文件夹中所有文件到 ConfigMap。路径相对于模板目录的父目录。注:两个函数均支持 Unix glob 模式,例如导入
conf.d/*.conf所有文件。
在 config.yaml 中指定模板:
yamltesting: replicas: 1 request_cpu: 100m request_memory: 128M some_option: disabled templates: - template: my-deployment.yaml.j2
同一模板可在多个环境中复用:
yamlstaging: ... templates: - template: my-deployment.yaml.j2 production-zone-1: ... templates: - template: my-deployment.yaml.j2
k8s-handle 使用 Jinja2 模板引擎,基于环境变量 TEMPLATES_DIR 指定的目录初始化。模板路径需相对于 TEMPLATES_DIR,例如:
模板目录结构:
templates / subdirectory / template_A.yaml template_B.yaml
在 template_A 中导入 template_B 需使用:
{% include "subdirectory/template_B.yaml" %}
对于包含多个独立组件(如主应用和迁移任务)的大型

manifest unknown 错误
TLS 证书验证失败
DNS 解析超时
410 错误:版本过低
402 错误:流量耗尽
身份认证失败错误
429 限流错误
凭证保存错误
来自真实用户的反馈,见证轩辕镜像的优质服务