欢迎访问我的博客,你的支持,是我最大的动力!

企业级容器集群构建(五)Kubernetes解决方案_健康/对外服务/多租户/节点管理/Helm

Docker 小马奔腾 3148℃ 评论
目录:
[显示]

《容器即服务.从零构建企业级容器集群》林帆2018.4 笔记

健康/对外服务/多租户/节点管理

健康检查

Probe探针功能为用户部署的服务提供精确到容器的健康检查功能,可以在某些容器出现故障时能及时进行路由屏蔽或重启

探针有两种类型:LivenessProbe、ReadinessProbe
LivenessProbe,当检查到容器不正常时,直接删除故障容器,根据pod中RestartPolicy属性决定是否重新创建一个
ReadinessProbe,当检查到容器不正常时,将该容器所属pod从所有使用它的Service对象的Endpoint里移除,即断开路由

探针判断容器是否健康有三种方式:执行指定的用户脚本、访问特定的HTTP路径、检查特定的TCP端口

每个容器最多可以有一个LivenessProbe和一个ReadinessProbe
上例中,若容器80端口不能访问,或指定的命令返回非0值,容器将判定为不健康,并将依据探针类型做出相应处理

提供对外服务

NodePort或LoadBalancer类型的Service对象,但会在所有node节点额外占用一个网络端口,且LoadBalancer只在特定云平台上可用

Ingress允许用户创建一个固定的出口,通过负载均衡对外提供服务,现有基于GEC和Nginx的7层IngressController镜像,实现基于域名的7层负载出口

Nginx的IngressController需开启k8s的ServiceAccount特性,即在启动kube-apiserver时,--admission-control参数中包含ServiceAccount

使用:gcr.io/google_containers/nginx-ingress-controller:0.8.3 [anjia0532/nginx-ingress-controller:0.8.3],该镜像启动时需指定一个默认服务后端,即当请求的目标域名和路径与所有已注册的Ingress项目都不匹配时,默认到的后端,通常使用 gcr.io/google_containers/defaultbackend:1.0 [anjia0532/google-containers.defaultbackend:1.0],该镜像的功能是除/healthz外,永远返回404

kubectl create -f 404-backend.rc.yaml
# 创建对应服务
kubectl expose rc 404-backend --port=80 --target-port=8080 --name=s404-backend

kubectl create -f nginx-ingress-controller.rc.yaml
由于IngressController已经使用hostPort监听所在节点的指定端口,因此不需要再创建额外的Serivce
当IngressController的pod启动后,其所在节点就成为Ingress配置的所有台后服务入口,因此需要固定它所运行的节点

添加后端服务容器
kubectl run echoheaders --image=anjia0532/google-containers.echoserver:1.4 --replicas=1 --port=8080
创建一个service
kubectl expose deployment echoheaders --port=80 --target-port=8080 --name=echoheaders
创建一个ingress规则描述文件

该规则文件定义两个合法请求路径:foo.com/foo和baz.com/bar
kubectl create -f echomap.ingress.yaml
访问
curl 127.0.0.1/foo -H 'Host: foo.com'
## 访问其他路径或用其他域名访问将返回404

多租户隔离和配额

k8s使用Namespace对象实现租户隔离功能,不同租户间不能看到对方创建的资源。对集群资源的限制也是基于租户设定的

资源限制有两种类型:
Resource Quota,对整个namespace内所有对象所用资源的总和进行限制
LimitRange,对指定namespace中每个pod或容器所用资源进行限制
这两种特定需要在kube-apiserver启动参数--admission-control参数中包含

Resource Quota限制的资源包括:CPU、内存、虚拟资源、Pod、Service等

示例:

新建命名空间
kubectl create namespace quota-example
应用pod-quota
kubectl create -f pod-quota.rq.yaml --namespace=quota-example
查看资源配额
kubectl describe resourcequota pod-quota --namespace=quota-example
##
创建一个pod
kubectl run nginx --image=nginx --replicas=1 --namespace=quota-example
kubectl get pods --namespace=quota-example
kubectl describe resourcequota pod-quota --namespace=quota-example
尝试将个数扩展到4个
kubectl scale deployment nginx --replicas=4 --namespace=quota-example
kubectl get pods --namespace=quota-example
由于资源配额的存在 实际只能创建两个pod

计算资源的配额比较特殊,一旦在namespace中使用此类资源配额,在创建pod时,必须指明所需资源的用量,否则会报错

资源需求总量:在资源调度时,目标node剩余计算资源满足requests的量,pod就可以调度到该节点,可视为pod的最小资源需求
资源限制总量:pod实际运行时能够使用的资源最大值,pod运行时不会超过限制的值

kubectl create -f cpu-mem-quota.rq.yaml --namespace=quota-example
应用限额后,新建pod必须指定需求和限制量,且不能超额
kubectl run nginx --image=nginx --replicas=1 --namespace=quota-example --requests=cpu=100m,memory=256Mi --limits=cpu=200m,memory=512Mi

使用LimitRange特性时,在启动kube-apiserver时,--admission-control参数值中要包含LimitRange

demo-limits.lr.yaml对pod和容器配额做了限制,其中容器配额还设置了default和defaultRequest,分别作为该namespace中创建容器的limits和requests资源的默认值

kubectl create namespace limit-example
kubectl create -f demo-limits.lr.yaml --namespace=limit-example
kubectl describe limits demo-limits --namespace=limit-example
应用
不满足限额的资源不会创建
kubectl run nginx --image=nginx --replicas=1 --namespace=limit-example --requests=cpu=200m,memory=256Mi --limits=cpu=200m,memory=512Mi

集群节点管理

节点也是一种资源对象,可以使用yaml来描述和管理

# 查看集群信息
kubectl cluster-info
# 查看节点
kubectl get node
# 查看详细yaml格式信息
kubectl get node -o yaml
# 保存某一节点的yaml描述
kubectl get node k8s-node -o yaml > k8s-node.yaml
# 删除节点
kubectl delete node k8s-node
kubectl delete -f k8s-node.yaml
# 添加节点
kubectl create -f k8s-node.yaml

默认,kubelet进程启动时,会向指向的集群master节点注册,因此直接登录目标节点重启kubelet服务也能将该节点加回集群
调试pod时,会依据节点可用计算资源和pod间关联关系,通过scheduler服务计算最佳目标节点
若希望特定的pod只运行在特定的节点上,可以使用节点标签和pod的nodeSelector属性实现
若使用了nodeSelector条件,但集群中没有包含相应标签的node时,pod最终会创建失败,即便有其他可供调度的node

# 为k8s-node2节点添加标签
kubectl label nodes k8s-node2 disk-type=ssd
# 查看标签
kubectl get node k8s-node2 -o yaml

kubectl create -f mongodb.pod.yaml
kubectl get pods -o wide

Kubernetes包管理工具Helm

使用kubectl和yaml文件无法向docker compose那样方便地查看和管理由特定的一组服务部署出来的服务集合,即服务编排

解决方案:Kompose 和 Helm
Kompose:https://github.com/kubernetes/kompose
Helm:https://github.com/helm/helm  官网:https://helm.sh/

Kompose将docker compose的yaml文件转换成一系列k8s资源描述文件,并未提供完整的编排管理功能
Helm能力不仅局限于服务编排管理,还提供发布版本管理、发布历史管理、指定版本回滚、服务发布仓库、参数化模板等功能

Helm是服务端/客户端架构。
服务端称为Tiller,是客户端与k8s交互的中介,并维护已部署到集群中的服务状态。Tiller没有数据库,使用k8s的ConfigMaps存储状态信息
客户端用于与用户交互,使用gRPC协议与Tiller通信,并与保存服务包文件的仓库通信
服务集合包称为Chart,客户端从仓库中获取Chart部署文件和相关配置,然后通过Tiller将Chart部署到集群

部署Helm

Helm客户端可在linux/mac/windows上运行,是一个单独的可执行文件

Helm下载:
https://storage.googleapis.com/kubernetes-helm/helm-v2.11.0-linux-amd64.tar.gz 【国内下载可能需要代理】

# 安装
wget https://storage.googleapis.com/kubernetes-helm/helm-v2.11.0-linux-amd64.tar.gz
tar zxf helm-v2.11.0-linux-amd64.tar.gz.tar
cd linux-amd64/
cp helm /usr/local/bin/
# 初始化
helm init
Creating /root/.helm
Creating /root/.helm/repository
Creating /root/.helm/repository/cache
Creating /root/.helm/repository/local
Creating /root/.helm/plugins
Creating /root/.helm/starters
Creating /root/.helm/cache/archive
Creating /root/.helm/repository/repositories.yaml
Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com
Adding local repo with URL: http://127.0.0.1:8879/charts
$HELM_HOME has been configured at /root/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.

Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
To prevent this, run helm init with the --tiller-tls-verify flag.
# 更新repo仓库
helm repo update
# 下载redis 0.10.2 的chart包 但不安装
helm fetch stable/redis --version 0.10.2 --untar

若k8s集群启用了RBAC功能,需要为helm创建一个专用帐号

Tiller服务端会在集群中kube-system命名空间下运行

故障解决1:Failed to pull image "gcr.io/kubernetes-helm/tiller:v2.11.0"
原因:k8s安装tiller默认会拉取gcr.io/kubernetes-helm/tiller:v2.11.0 同时默认仓库是https://kubernetes-charts.storage.googleapis.com 这两个地址国内访问存在问题
解决:使用阿里的服务
helm init --upgrade -i registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.11.0 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts

故障解决2:执行helm version 显示E1017 19:40:21.108430 2661 portforward.go:331] an error occurred forwarding 40857 -> 44134: error forwarding port 44134 to pod , uid : unable to do port forwarding: socat not found.
原因:tiller镜像运行所在节点没有安装socat
解决:kubectl -n kube-system get pods -o wide|grep tiller 查看tiller所在节点
yum install socat [建议所有node节点都安装]

helm常用命令
# 创建一个新的chart
helm create myapp
# 查看在存储库中可用的所有Helm charts
helm search
# 更新charts列表以获取最新版本
helm repo update
# 查看在群集上安装的Charts列表
helm list
helm使用

下载0.10.2的redis的chart包 不安装
helm fetch stable/redis --version 0.10.2 --untar
检测指定目录中文件是否符合chart的结构
helm lint redis

标准Chart目录结构
README.md,项目描述文件 说明该Chart的用法和参数
Chart.yaml,主配置文件 包含Chart名称、版本和其他元数据信息
values.yaml,定义模板文件中变量的默认值
templates/,模板文件(k8s资源描述文件)
额外文件
LICENSE,使用协议
requirements.yaml,存放当前chart依赖的其他chart的说明
charts/,当前chart依赖的其他chart

# 使用helm安装服务
helm install ./redis --name demo-redis
helm install redis-0.10.2.tgz
helm install stable/redis
helm install stable/mariadb --version 0.3.0

服务编排时,需要依据具体环境配置的内容会的默认值保存在values.yaml中,部署时可以使用--set参数修改其中的部分变量值
helm install --set resources.requests.memory=512Mi mariadb
或者将要覆写的变量保存为单独文件,部署时用-f加载
helm install -f prod_values.yaml mysql
列出所有部署的包
helm ls
# 部署到集群中的chart在helm中称为release,若部署时没有指定名称,会随机生成一个名称
查看某release详细信息
helm status demo-redis
升级包
helm upgrade demo-redis -f prod_values.yaml --set resources.requests.memory=1024Mi ./redis
# 升级实际上是用新的Pod替代旧的

chart实例是有部署版本的,从1开始,每次更新配置都会递增
查看更新历史
helm history demo-redis
通过版本号可以回滚到任意一个历史版本
helm rollback demo-redis 1
删除已部署的chart
helm delete demo-redis
# 注意 该操作实际上只是逻辑删除 将服务停止并标记为已删除 并未清除相关数据 helm ls -a/--all 可以查看包含已删除的实例 其历史记录也在
恢复一个已删除的chart
helm history demo-redis
helm rollback demo-redis 1
彻底删除chart实例
helm delete --purge demo-redis

自定义Chart

创建标准Chart模板目录结构
helm create demochart
demochart/
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── ingress.yaml
│   ├── NOTES.txt
│   └── service.yaml
└── values.yaml
其中templates目录中自动创建的文件不是必需的
NOTES.txt,安装chart时自动显示的用户帮助文档 如使用和配置方法
deployment.yaml,创建Deployment的资源描述示例
service.yaml,创建Service的资源描述示例
ingress.yaml,创建Ingress资源的描述示例
_helpers.pl,定义一些可以在chart中引用的yaml内容片段

通常会直接删除templates目录里默认创建的文件,将真实的服务资源描述文件放进去,然后将需要复用或复杂的片段抽离到_helpers.tpl,再创建一个NOTES.txt,写入自己chart的基本使用说明

templates目录中的文件都是资源描述模板,可以嵌入 {{表达式}} 格式的变量数据和简单数据计算。可以使用模板占位符、内置对象、函数、控制语句、模板变量等特性。

模板占位符

引用一个在模板以外定义的数据
数据来源:values.yaml文件  执行helm install/update时,通过 -f 或 --set 设置的数据
用法:
{{ .Values.configmap.version }} 表示外部定义的,名为 configmap.version 的数据

内置对象

以 . 开头,由Helm提供数据
包含Chart实例信息的Release对象;包含Chart包信息的Chart对象;包含Helm和k8s系统信息的Capabilities对象;包含当前模板信息的Template对象等
用法:
{{ .Release.Name }} 表示当前Chart实例名字

函数

用于对数值内容进行加工,| 是管道操作符,函数大多来自于Go语言的Sprig库
用法:
{{ now | htmlDate }} 获取当前时间并调整显示格式
常用函数:
quote,为原始内容加上引号,并自动转义原有的引号字符
lower,转换为小写;upper,转换为大写
trim,去掉原始内容前后空白字符
nospace,去掉所有空格
substr,截取原内容中一段字符
randNumeric,产生指定长度随机数字串
randAscii,产生指定长度随机字符串
indent,将原始内容缩进指定空格数
replace,替换原始内容中特定字符串

控制语句

逻辑判断/循环控制
相等 eq ;不相等 ne ;比较大小 lt gt

{{ if eq .Values.server.type "redis" }}
specs: 2c8g
{{ else if eq .Values.server.type "mysql" }}
specs: 2c4g
{{ else }}
specs: 2c2g
{{ end }}
## with语句可以简化属性访问,如 .name 等于 .Values.server.name
{{- with .Values.server }}
name: {{ .name | upper | quote }}
port: {{ .port | default "5000" }}
{{- end }}

模板变量

有些控制流需要和变量配合使用,如

# 循环语句
{{- range $key,$val := .Values.env_variables }}
{{ $key }}: {{ $var | quote }}
{{- end }}

移除空白

去掉生成模板中不必要的空格或空行
控制语句最后会变成一个空行
语法: {{- 和 -}} 注意 - 和 }} 之间没有空格
{{- ,移除当前占位字段左侧所有空白内容,包括换行符
-}} ,移除当前占位字段右侧所有空白内容,包括换行符
同时使用会使上行两行合并

引用模板段

对可以被复用的模板段,可以抽离到 _helpers.tpl 文件中,也可以放在模板文件里
使用 define语句定义,使用template引用

Chart仓库

可以使用官方仓库,也能创建私有仓库
Chart仓库实际上只是普通HTTP文件服务器,使用单层目录结构,存放Chart压缩包和一个index.yaml文件。其中index.yaml是仓库索引文件
默认的local仓库要启用,需要执行helm serve 创建http服务

# 查看仓库列表
helm repo list
NAME URL
stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
local http://127.0.0.1:8879/charts
# 创建本地仓库
mkdir charts
helm serve --address 0.0.0.0:8879 --repo-path ./charts
# 打包
helm package redis
# 添加包到私有仓库
mv redis-0.10.2.tgz charts/
helm repo index ./charts/
# 更新客户端
helm repo update
helm search redis
# 添加其他仓库
helm repo add <名称> <仓库URL>

 

转载请注明:轻风博客 » 企业级容器集群构建(五)Kubernetes解决方案_健康/对外服务/多租户/节点管理/Helm

喜欢 (0)or分享 (0)