kubetpl - kubernetes 模板管理工具

简介: kubetpl - kubernetes 模板管理工具

Helm、Kustomize、Kubetpl

  • 本人实际没有使用过 Helm 和 Kustomiz 这两款工具,以下的对比,仅个人观点,仅供参考;如果有说的不对的地方,还望指点

Helm

  • 在有网络的情况下
  • Helm 可以很好的进行产品的迭代升级,只需要配置好 repo 仓库,拉取相应版本的 chart 包,修改对应的 values.yaml 文件就可以完成
  • 对于需要快速部署一些主流的中间件或者服务的时候,可以不需要去考虑自己需要准备那些对象(deployment、service、configmap等等),因为仓库里面都有现成的,不需要自己造轮子,拿来就可以用
  • 在没有网络的情况下
  • 比如一些 saas 类型的产品交付公司,在一些银行、证券类的客户现场,大多数的生产环境是不通外网的,在这些苛刻条件下,如果使用 Helm 就会需要涉及 Helm 的私仓,相对于交付来说,架构会过于庞大且麻烦

Kustomize

  • Helm 对于服务的定制仅限于预置变量,那么如果需要更多更灵活的的 YAML 定制就需要用到 Kustomize
  • Kustomize 是一套采用合并思想,对 Kubernetes 原生配置进行管理的工具,使用无模板的方案定义应用配置
  • 允许用户使用一系列的描述文件为基础,然后通过 overlay 的方式生成最终部署应用所需的描述文件

Kubetpl

  • 有点类似于 Helm 的 values.yaml 的方式配置相应的变量,通过预先配置好的 yaml 文件模板,带入变量后生成新的 yaml 文件
  • 可以定制化配置不同场景的模板,不过模板的管理会相对麻烦很多
  • 比较轻量化,不需要任何服务器组件,只是单纯的配置和管理 yaml 文件

安装 Kubetpl

curl -sSL https://github.com/shyiko/kubetpl/releases/download/0.9.0/kubetpl-0.9.0-$(
    bash -c '[[ $OSTYPE == darwin* ]] && echo darwin || echo linux'
  )-amd64 -o kubetpl && chmod a+x kubetpl && sudo mv kubetpl /usr/local/bin/

Kubetpl 命令参数

参数选项

  • completion - 命令行参数自动补齐
  • help - 命令帮助
  • render - 渲染模板
completion - 参数自动补齐
  • 可选参数:bashzsh
# bash
source <(kubetpl completion bash)
# zsh
source <(kubetpl completion zsh)
ender - 渲染模板

image.png关于模板风格:$,go-template,template-kind ,主要区别在于变量引用的方式不同

  • $-shell 的风格
  • $NAME

go-template - go 语言 template 库的风格

  • {{ .VAR }} - 获取变量名称为 VAR 的变量值
  • {{ if isset "VAR" }} ... {{ end }} - 当定义了 VAR 变量的时候才会在 }} ... {{ 中间展示变量值
  • {{ get "VAR" "default" }} - 获取 VAR 的值,如果未设置,则返回 "default"
  • {{ .VAR | quote }} - 引用 VAR 值
  • {{ .VAR | indent 4 }} - VAR 的缩进值(带 4 个空格)
  • {{ .VAR | b64enc }} - VAR 值以 base64 编码展示
  • template-kind - 没太看懂....

go-template 语法

  • 本人没有接触过 go 语言,临时找了一些资料来学习一些简单的使用
  • go 语言的变量好像是不支持 - 出现在变量名称内的,go 语言使用的是驼峰命名,不然可能会有这样的报错:
  • template: nginx-template.yaml:3: unexpected bad character U+002D '-' in range

注释

{{/* 注释 */}}

引用变量

  • 输出 hostAlias 变量的值
{{ .hostAlias }}
  • hostAlias 是匿名字段时,可以访问其内部字段或方法
{{ .hostAlias.ip }}
  • 如果需要引用外部变量,需要在前面加上 $ 符号
{{ $.hostAlias }}

在 template 中定义变量

  • 变量名称前面需要带上 $ 符号
  • 使用 := 来对变量赋值
{{ $x := "hello" }}
  • 定义变量的值引用其他变量的值
{{ $x := .hostAlias }}

条件判断

  • if 后面可以是一个条件表达式(包括管道函数表达式。pipeline 即管道)
  • 也可以是一个字符串变量布尔值变量
  • 当为字符串变量时,如为空字符串则判断为 false,否则判断为 true
{{ if .hostAlias }}
- ip: {{ .ip }}
  hostnames: {{ .hostnames }}
{{ end }}

遍历

  • 普通用法,当变量值存在时才会有后面的内容输出
{{ range $.hostAliases }}
- ip: {{ .ip }}
  hostnames: {{ .hostnames }}
{{ end }}
  • 另一种用法
{{ range $k,$v := .labels }}
{{ $k }}: {{ $v }}
{{ end }}

开始使用

简单使用

准备一个 yaml 模板
  • 这里直接从 github 上面复制过来用了,以下所有的 yaml 文件只是用来模拟 kubetpl 生成 yaml 文件使用的,不能被直接使用的

# kubetpl:syntax:go-template

  • 定义模板风格,如果不在模板文件内定义,则需要通过 --syntax 的方式申明,否则会有类似如下报错

does not appear to be a valid YAML (yaml: line 3: did not find expected key).

Did you forget to specify --syntax=<$|go-template|template-kind> / add "# kubetpl:syntax:<$|go-template|template-kind>"?

# kubetpl:syntax:go-template
apiVersion: v1
kind: Service
metadata:
  name: {{ .NAME }}-service
spec:
  selector:
    app: {{ .NAME }}
  ports:
  - protocol: TCP
    port: 80
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: {{ .NAME }}-deployment
spec:
  replicas: {{ .REPLICAS }}
  template: 
    metadata:
      labels:
        app: {{ .NAME }}
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
准备变量文件
  • 支持的格式
  • *.env - <var>=<value>
  • yaml/json 文件

*.env 的方式

cat << EOF > valus.env
NAME=sample-app
REPLICAS=2
EOF

yaml 文件 的方式

cat << EOF > env.yaml
NAME: my-nginx
REPLICAS: 3
EOF
生成新的 yaml 文件
  • 两个变量文件定义的变量值是有差异的,这个单纯就是用来比较使用的,只是选择哪种变量文件,全看各自的选择
# 使用 valus.env
kubetpl render nginx-template.yaml -i valus.env -o nginx-env.yaml
# 使用 env.yaml
kubetpl render nginx-template.yaml -i env.yaml -o nginx-yaml.yaml

稍微复杂一点的场景

  • 因为 kubetpl 是通过 -i 的方式引入的变量,所以下面的变量引用都需要加上 $ 符号表示外部引入变量,才能正常识别,不然会有类似如下的报错:
  • template: nginx-template.yaml:9:23: executing "nginx-template.yaml" at <.static.namespace>: map has no entry for key "static"
准备一个 yaml 模板
# kubetpl:syntax:go-template
{{ range $getName := .staticInfo }}
---
apiVersion: v1
kind: Service
metadata:
  name: {{ $getName.name }}-svc
  namespace: {{ $.static.namespace }}
spec:
  selector:
    app: {{ $getName.name }}
  ports:
  - protocol: TCP
    port: {{ $getName.port }}
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: {{ $getName.name }}
  namespace: {{ $.static.namespace }}
spec:
  replicas: {{ $.static.replicas }}
  template:
    metadata:
      labels:
        app: {{ $getName.name }}
    spec:
      containers:
      - name: {{ $getName.name }}
        image: {{ $.global.Image }}
        imagePullPolicy: {{ $.global.ImagePull }}
        ports:
        - containerPort: 80
{{ end }}
准备变量文件
global:
  Image: nginx:1.16
  ImagePull: IfNotPresent
static:
  namespace: web-static
  replicas: 3
staticInfo:
  - name: app-static
    port: 80
  - name: backend-static
    port: 8080
生成新的 yaml 文件
kubetpl render nginx-template.yaml -i env.yaml -o nginx.yaml
生成后的 yaml 文件
---
apiVersion: v1
kind: Service
metadata:
  name: app-static-svc
  namespace: web-static
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    app: app-static
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: app-static
  namespace: web-static
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: app-static
    spec:
      containers:
      - image: nginx:1.16
        imagePullPolicy: IfNotPresent
        name: app-static
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: backend-static-svc
  namespace: web-static
spec:
  ports:
  - port: 8080
    protocol: TCP
  selector:
    app: backend-static
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: backend-static
  namespace: web-static
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: backend-static
    spec:
      containers:
      - image: nginx:1.16
        imagePullPolicy: IfNotPresent
        name: backend-static
        ports:
        - containerPort: 80

kubetpl/data-from-file

  • 当我们需要配置 configmap 的时候,可以通过文件带入的形式来配置 yaml 文件,这样可以单独维护 configmap 给所有的 yaml 文件来使用,对于维护来说,能减轻不少的成本
准备一个 yaml 模板
# kubetpl:syntax:go-template
---
apiVersion: v1
kind: ConfigMap
kubetpl/data-from-file:
  - ./nginx.conf
metadata:
  name: {{ $.configmap.name }}
  namespace: {{ $.static.namespace }}
data:
{{ range $getName := .staticInfo }}
---
apiVersion: v1
kind: Service
metadata:
  name: {{ $getName.name }}-svc
  namespace: {{ $.static.namespace }}
spec:
  selector:
    app: {{ $getName.name }}
  ports:
  - protocol: TCP
    port: {{ $getName.port }}
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: {{ $getName.name }}
  namespace: {{ $.static.namespace }}
spec:
  replicas: {{ $.static.replicas }}
  template:
    metadata:
      labels:
        app: {{ $getName.name }}
    spec:
      containers:
      - name: {{ $getName.name }}
        image: {{ $.global.Image }}
        imagePullPolicy: {{ $.global.ImagePull }}
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-conf
          mountPath: /workspace/nginx/conf
    volumes:
    - name: nginx-conf
      configMap:
        name: {{ $.configmap.name }}
{{ end }}
准备变量文件
  • 对比前面的,增加了一个 configmap
global:
  Image: nginx:1.16
  ImagePull: IfNotPresent
static:
  namespace: web-static
  replicas: 3
staticInfo:
  - name: app-static
    port: 80
  - name: backend-static
    port: 8080
configmap:
  name: static-cm
准备 file 文件
  • 命名为 nginx.conf
user root;
worker_processes 4;
error_log  logs/nginx_error.log  warn;
pid  logs/nginx.pid;
worker_rlimit_nofile 51200;
events {
  use epoll;
  worker_connections 51200;
  multi_accept on;
}
http {
  include       mime.types;
  default_type  application/octet-stream;
  server_names_hash_bucket_size 128;
  client_header_buffer_size 256k;
  large_client_header_buffers 16 256k;
  client_max_body_size 1m;
  keepalive_timeout 0;
  client_body_timeout 10;
  client_header_timeout 10;
  send_timeout 5;
  sendfile on;
  tcp_nopush  on;
  tcp_nodelay on;
  gzip on;
  gzip_min_length  1k;
  gzip_buffers     4 16k;
  gzip_http_version 1.0;
  gzip_comp_level 5;
  gzip_disable "MSIE [1-6].";
  gzip_types text/plain application/x-javascript text/css text/javascript application/x-httpd-php image/jpeg image/gif image/png application/json;
  gzip_vary on;
  ssi on;
  ssi_silent_errors on;
  ssi_types text/shtml;
  proxy_temp_path proxy_temp 1 2;
  client_body_temp_path client_body_temp 1 2;
  fastcgi_temp_path fastcgi_temp 1 2;
  uwsgi_temp_path uwsgi_temp 1 2;
  scgi_temp_path scgi_temp 1 2;
  set_real_ip_from 0.0.0.0/0;
  real_ip_header  X-Forwarded-For;
  real_ip_recursive   on;
  underscores_in_headers on;
  resolver kube-dns.kube-system valid=5s;
  resolver_timeout 5s;
  access_log off;
  server {
      listen       8080;
      server_name  test.com;
      set $proto_host "${http_x_forwarded_proto}_${host}";
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
      location /static/ {
        location ~* \.(gif|jpg|jpeg|png|bmp|swf|ico)$ {
          expires      30d;
        }
        expires 1h;
      }
  }
}
生成新的 yaml 文件
  • 使用 kubetpl/data-from-file 的话,需要加上 --allow-fs-access 参数,不然会出现类似如下的报错:
  • nginx-template.yaml: access denied: nginx.conf (use --allow-fs-access and/or -c/--chroot=<root dir, e.g. '.'> to allow)
kubetpl render --allow-fs-access nginx-template.yaml -i env.yaml -o nginx.yaml
生成后的 yaml 文件
---
apiVersion: v1
data:
  nginx.conf: |
    user root;
    worker_processes 4;
    error_log  logs/nginx_error.log  warn;
    pid  logs/nginx.pid;
    worker_rlimit_nofile 51200;
    events {
      use epoll;
      worker_connections 51200;
      multi_accept on;
    }
    http {
      include       mime.types;
      default_type  application/octet-stream;
      server_names_hash_bucket_size 128;
      client_header_buffer_size 256k;
      large_client_header_buffers 16 256k;
      client_max_body_size 1m;
      keepalive_timeout 0;
      client_body_timeout 10;
      client_header_timeout 10;
      send_timeout 5;
      sendfile on;
      tcp_nopush  on;
      tcp_nodelay on;
      gzip on;
      gzip_min_length  1k;
      gzip_buffers     4 16k;
      gzip_http_version 1.0;
      gzip_comp_level 5;
      gzip_disable "MSIE [1-6].";
      gzip_types text/plain application/x-javascript text/css text/javascript application/x-httpd-php image/jpeg image/gif image/png application/json;
      gzip_vary on;
      ssi on;
      ssi_silent_errors on;
      ssi_types text/shtml;
      proxy_temp_path proxy_temp 1 2;
      client_body_temp_path client_body_temp 1 2;
      fastcgi_temp_path fastcgi_temp 1 2;
      uwsgi_temp_path uwsgi_temp 1 2;
      scgi_temp_path scgi_temp 1 2;
      set_real_ip_from 0.0.0.0/0;
      real_ip_header  X-Forwarded-For;
      real_ip_recursive   on;
      underscores_in_headers on;
      resolver kube-dns.kube-system valid=5s;
      resolver_timeout 5s;
      access_log off;
      server {
          listen       8080;
          server_name  test.com;
          set $proto_host "${http_x_forwarded_proto}_${host}";
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
          location /static/ {
            location ~* \.(gif|jpg|jpeg|png|bmp|swf|ico)$ {
              expires      30d;
            }
            expires 1h;
          }
      }
    }
kind: ConfigMap
metadata:
  name: static-cm
  namespace: web-static
---
apiVersion: v1
kind: Service
metadata:
  name: app-static-svc
  namespace: web-static
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    app: app-static
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: app-static
  namespace: web-static
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: app-static
    spec:
      containers:
      - image: nginx:1.16
        imagePullPolicy: IfNotPresent
        name: app-static
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /workspace/nginx/conf
          name: nginx-conf
    volumes:
    - configMap:
        name: static-cm
      name: nginx-conf
---
apiVersion: v1
kind: Service
metadata:
  name: backend-static-svc
  namespace: web-static
spec:
  ports:
  - port: 8080
    protocol: TCP
  selector:
    app: backend-static
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: backend-static
  namespace: web-static
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: backend-static
    spec:
      containers:
      - image: nginx:1.16
        imagePullPolicy: IfNotPresent
        name: backend-static
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /workspace/nginx/conf
          name: nginx-conf
    volumes:
    - configMap:
        name: static-cm
      name: nginx-conf


相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
目录
相关文章
|
3月前
|
Kubernetes Shell Linux
K8S 实用工具之一 - 如何合并多个 kubeconfig?
K8S 实用工具之一 - 如何合并多个 kubeconfig?
|
5月前
|
Kubernetes 负载均衡 应用服务中间件
k8s学习-Ingress(安装、模板、创建、删除)
k8s学习-Ingress(安装、模板、创建、删除)
108 0
|
5月前
|
Kubernetes 负载均衡 网络协议
k8s学习-Service(概念、模板、创建、外部代理、删除等)
k8s学习-Service(概念、模板、创建、外部代理、删除等)
159 0
|
4月前
|
存储 Kubernetes C++
Kubernetes VS Docker Swarm:哪个容器编排工具更适合你?
当今,容器化技术已成为IT领域的热门话题,而容器编排工具是实现容器自动化部署和管理的关键。本文将比较两种主流的容器编排工具Kubernetes和Docker Swarm,并探讨它们的优缺点,以帮助你选择最适合自己的工具。
|
5月前
|
Kubernetes Perl 容器
k8s学习-ReplicationController 、ReplicaSet(工作原理、模板、实战)
k8s学习-ReplicationController 、ReplicaSet(工作原理、模板、实战)
40 0
|
5月前
|
运维 Kubernetes Cloud Native
k8s学习-Pod(生命周期、探针、模板、创建、删除等)
k8s学习-Pod(生命周期、探针、模板、创建、删除等)
62 0
|
4月前
|
Kubernetes 调度 C++
Kubernetes vs Docker Swarm:容器编排工具的比较与选择
在当今云计算时代,容器技术的应用越来越广泛。而在众多容器编排工具中,Kubernetes和Docker Swarm是两个备受关注的竞争者。本文将深入比较这两个工具的特点、优势和劣势,帮助读者更好地选择适合自己的容器编排解决方案。
|
3月前
|
Kubernetes 开发者 Docker
K8S 实用工具之五 -kompose
K8S 实用工具之五 -kompose
|
5月前
|
存储 Kubernetes 网络协议
k8s学习-StatefulSet(模板、更新、扩缩容、删除等)
k8s学习-StatefulSet(模板、更新、扩缩容、删除等)
145 0
|
3月前
|
存储 监控 测试技术
【Docker管理工具】安装Oxker容器管理工具
【2月更文挑战第4天】安装Oxker容器管理工具
84 2