目录
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 - 参数自动补齐
- 可选参数:
bash
和zsh
# bash
source <(kubetpl completion bash)
# zsh
source <(kubetpl completion zsh)
render - 渲染模板
参数 | 解释 |
---|---|
--allow-fs-access |
--chroot=<directory containing template> 的 缩写 |
-c, --chroot string |
kubetpl/data-from-file 允许读取的文件的路径,--chroot 以外的文件都会被拒绝访问 ;在模板文件中可以写好路径,使用 --allow-fs-access 参数也可以实现 |
-z, --freeze --freeze-list stringSlice --freeze-ref stringArray --ignore-unset |
冻结 ConfigMap/Secret <kind>/<name> 的方式冻结,例如(ConfigMap/foo, Secret/bar) 不应包含在输出中的外部 ConfigMap/Secret,但需要对其进行 --freeze 的引用 如果未设置,则保留 $VAR/${VAR}(例如,"echo 'kind:$A$B'|kubetpl r --s A=X --syntax=$ --ignore-unset" 输出:"kind:X$B" )` |
-i, --input stringArray |
指定配置文件:*.{env,yml,yaml,json} |
-o, --output string |
指定输出的文件名称 |
-s, --set stringArray |
<var>=<value> 的形式申明变量 如果 --input 有配置则以 --input 优先 变量少的情况下,可以不写 --input,直接使用 --set 申明 |
-x, --syntax string |
定义模板风格 $,go-template,template-kind - 三个可选项 |
关于模板风格:
$,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
最后推荐几在找资料的时候看到的文章和大家一起学习
- Kubernetes 资源编排系列之一: Pod YAML 篇
- Kubernetes 资源编排系列之二: Helm 篇
- Kubernetes 资源编排系列之三: Kustomize 篇
- golang 模板语法简明教程