Skip to content

9 Kubernetes-Helm应用

在 Kubernetes 中,将集群环境部署简单化。让 Kubernetes 中的应用,能动态生成

一、概念

核心概念:

​ chart:类似 docker-compose 的 yaml 文件

​ release:部署的项目(实例)

chart,可动态化运行为,release

Helm 包含两个组件:

Helm 客户端和 Tiller 服务器,如下图所示

image-20230207202039320

Helm 客户端负责 chart 和 release 的创建和管理以及和 Tiller 的交互。Tiller 服务器运行在 Kubernetes 集群中,它会处理 Helm 客户端的请求,与 Kubernetes API Server 交互

HELM 版本

V2版本(现存)、V3版本(未来)区别:

​ V3版本更稳定

image-20230207202550593

二、HELM 部署

注意:HELM 对时间同步要求高

1、下载 或上传 helm

直接下载:

$ ntpdate ntp1.aliyun.com
$ wget https://storage.googleapis.com/kubernetes-helm/helm-v2.13.1-linux-amd64.tar.gz
$ tar -zxvf helm-v2.13.1-linux-amd64.tar.gz
$ cd linux-amd64/
$ cp helm /usr/local/bin/

本地上传压缩包:

image-20230207203241003

[root@k8s-master01 helm]# tar -xf helm-v2.13.1-linux-amd64.tar.gz 
[root@k8s-master01 helm]# cp -a linux-amd64/helm /usr/local/bin/

2、每个节点导入 创建 tiller 所需镜像

[root@k8s-master01 helm]# scp helm-tiller.tar root@n1:/root/
root@n1's password: 
helm-tiller.tar                        100%   81MB  41.9MB/s   00:01    
[root@k8s-master01 helm]# scp helm-tiller.tar root@n2:/root/



[root@k8s-master01 helm]# docker load -i helm-tiller.tar

[root@k8s-node01 ~]# docker load -i helm-tiller.tar

[root@k8s-node02 ~]# docker load -i helm-tiller.tar

3、创建 tiller,并进行集群角色绑定

[root@k8s-master01 helm]# vim rbac.yaml 
[root@k8s-master01 helm]# cat rbac.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: tiller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: tiller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: tiller
    namespace: kube-system


[root@k8s-master01 helm]# kubectl apply -f rbac.yaml 

[root@k8s-master01 helm]# helm init --service-account tiller --skip-refresh

# 检查tiller运行
[root@k8s-master01 helm]# kubectl get pod -A |grep tiller
kube-system     tiller-deploy-58565b5464-tsdpf              1/1     Running   0          135m


# 查看helm版本
[root@k8s-master01 ~]# helm version
Client: &version.Version{SemVer:"v2.13.1", GitCommit:"618447cbf203d147601b4b9bd7f8c37a5d39fbb4", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.13.1", GitCommit:"618447cbf203d147601b4b9bd7f8c37a5d39fbb4", GitTreeState:"clean"}

三、HELM 常用命令

HELM 常用命令.md

$ helm install .                # 基于当前目录部署应用
$ helm ls                       # 列出helm
$ helm delte helm名              # 删除helm
$ helm upgrade -f 文件名 helm名 .       # 基于文件升级应用
$ helm upgrade -f 文件名 helm名 --set image,tag=v3 .    # 命令升级
$ helm repo list                # 查看本地 helm 使用的仓库地址



# 列出已经部署的 Release
$ helm ls
# 查询一个特定的 Release 的状态
$ helm status RELEASE_NAME
# 移除所有与这个 Release 相关的 Kubernetes 资源
$ helm delete cautious-shrimp
# helm rollback RELEASE_NAME REVISION_NUMBER
$ helm rollback cautious-shrimp 1
# 使用 helm delete --purge RELEASE_NAME 移除所有与指定 Release 相关的 Kubernetes 资源和所有这个 Release 的记录
$ helm delete --purge cautious-shrimp
$ helm ls --deleted

0)部署一个简单环境:

1、创建文件夹

$ mkdir ./hello-world
$ cd ./hello-world

2、创建自描述文件 Chart.yaml (这个文件必须有 name 和 version 定义)

$ cat <<'EOF' > ./Chart.yaml
name: hello-world
version: 1.0.0
email: wanganglinux@gmail.com
EOF

3、创建模板文件, 用于生成 Kubernetes 资源清单(manifests)

$ mkdir ./templates

$ cat <<'EOF' > ./templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: hello-world
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
        - name: hello-world
          image: wangyanglinux/myapp:v1
          ports:
            - containerPort: 80
              protocol: TCP
EOF

$ cat <<'EOF' > ./templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: hello-world
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: hello-world
EOF

4、 部署环境

使用命令 helm install RELATIVE_PATH_TO_CHART 创建一次Release

$ helm install .

5、浏览器测试访问

部署成功

image-20230207205517392

6、配置体现在配置文件 values.yaml

$ cat <<'EOF' > ./values.yaml
image:
  repository: wangyanglinux/myapp
  tag: v1
EOF

# 这个文件中定义的值,在模板文件中可以通过 .VAlues对象访问到
$ cat <<'EOF' > ./templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: hello-world
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
        - name: hello-world
          image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
          ports:
            - containerPort: 80
              protocol: TCP
EOF

# 在 values.yaml 中的值可以被部署 release 时用到的参数 --values YAML_FILE_PATH 或 --set key1=value1, key2=value2 覆盖掉
$ helm install --set image.tag='latest' .

# 升级版本
helm upgrade  -f values.yaml helm名 .

image-20230208084841113

7、Debug

# 使用模板动态生成K8s资源清单,非常需要能提前预览生成的结果。
# 使用--dry-run --debug 选项来打印出生成的清单文件内容,而不执行部署
helm install . --dry-run --debug --set image.tag=latest

四、HELM 部署 dashboard

GUI 管理 Kubernetes 集群

1、找到镜像,chart包

Ⅰ、上传镜像到私有仓库:

image-20230208182358142

# 导入dashboard镜像
[root@k8s-master01 ~]# docker load -i dashboard.tar 
fbdfe08b001c: Loading layer  122.3MB/122.3MB
Loaded image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1

# 修改标签
[root@k8s-master01 ~]# docker tag k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1 harbor.yq.com/library/kubernetes-dashboard-amd64:v1.10.1

# 登录私有仓库
[root@k8s-master01 ~]# docker login harbor.yq.com -u admin -p Harbor12345 
...
Login Succeeded

# 上传镜像
[root@k8s-master01 ~]# docker push harbor.yq.com/library/kubernetes-dashboard-amd64:v1.10.1

Ⅱ、上传chart包

image-20230208183023001

2、HELM 安装 dashboard

Ⅰ、解压 dashboard 的 chart 包到指定位置

[root@k8s-master01 dashboard]# pwd
/usr/local/kubernetes/helm/dashboard
[root@k8s-master01 dashboard]# tar -xf kubernetes-dashboard-1.8.0.tgz

[root@k8s-master01 dashboard]# cd kubernetes-dashboard
[root@k8s-master01 kubernetes-dashboard]#

Ⅱ、编写新的 yaml 文件

​ 修改镜像地址为私有仓库

​ 关闭ingress

[root@k8s-master01 kubernetes-dashboard]# vim dashboard.yaml
[root@k8s-master01 kubernetes-dashboard]# cat dashboard.yaml
image:
  repository: harbor.yq.com/library/kubernetes-dashboard-amd64
  tag: v1.10.1
ingress:
  enabled: false
  hosts: 
    - k8s.frognew.com
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
  tls:
    - secretName: frognew-com-tls-secret
      hosts:
      - k8s.frognew.com
rbac:
  clusterAdminRole: true

Ⅲ、helm 部署

helm install . -n kubernetes-dashboard --namespace kube-system -f dashboard.yaml

Ⅳ、修改 service 为NodePort,将服务暴露出去

​ 也可以部署 ingress实现

$ kubectl edit svc -n kube-system kubernetes-dashboard

image-20230208184104555

[root@k8s-master01 kubernetes-dashboard]# kubectl get svc -n kube-system |grep dashboard
kubernetes-dashboard   NodePort    10.107.63.76    <none>        443:31782/TCP            4m29s

3、证书相关配置

Ⅰ、创建证书

$ pwd
/usr/local/kubernetes/helm/dashboard
$ mkdir cert;cd cert


$ openssl genrsa -des3 -out server.key 2048
$ openssl req -new -key server.key -out server.csr
$ cp server.key server.key.org
$ openssl rsa -in server.key.org -out server.key
$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Ⅱ、替换 dashboard 默认证书

$ kubectl delete secret kubernetes-dashboard -n kube-system

$ pwd
/usr/local/kubernetes/helm/dashboard/cert
$ mv server.key tls.key
$ mv server.crt tls.crt

$ kubectl create secret generic kubernetes-dashboard --from-file=tls.key --from-file=tls.crt -n kube-system

Ⅲ、修改 dashboard 的 deployment 控制器,识别证书文件

$ kubectl edit deployment kubernetes-dashboard -n kube-system


        - --tls-key-file=tls.key
        - --tls-cert-file=tls.crt

image-20230208184921872

# dashboard的pod运行成功
$ kubectl get pod -n kube-system |grep dashboard
kubernetes-dashboard-5b99fb7b49-k6f87   1/1     Running   0          31s


# 获取svc的地址
$ kubectl get svc -n kube-system |grep dashboard
kubernetes-dashboard   NodePort    10.100.101.159   <none>        443:30301/TCP            2m58s

4、浏览器登录

Ⅰ、浏览器输入地址登录

image-20230208190905759

image-20230208191015184

Ⅱ、获取 token(令牌)

​ 如果选择kubeconfig文件认证,将 ~/.kube/config 文件上传。本次采用令牌认证

$ kubectl get secret -n kube-system |grep dashboard-token
kubernetes-dashboard-token-kfmvk                 kubernetes.io/service-account-token   3      6m32s


$ kubectl describe secret kubernetes-dashboard-token-kfmvk -n kube-system
Name:         kubernetes-dashboard-token-kfmvk
Namespace:    kube-system
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: kubernetes-dashboard
              kubernetes.io/service-account.uid: 13b5b878-fd84-4ae2-b511-555a7027f30b

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1025 bytes
namespace:  11 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC10b2tlbi1rZm12ayIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjEzYjViODc4LWZkODQtNGFlMi1iNTExLTU1NWE3MDI3ZjMwYiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTprdWJlcm5ldGVzLWRhc2hib2FyZCJ9.pJuNoplIrp6MT6BGLZEC-UzkdbZ6ytpuSl48ShPLF7jozpSIpLE4J51QfwNZX9bN0CP6zDpKGeX_KkyN10I2bzAJsDFQe83XGPLI3jNZGoO0jS3Row73z09IfczcTmw6fnZX2Ar1JoJ8wf5NqTJDdkLECrFyReacjZL5JjzzYH91ZGn2UJpLKYoedgLVY_5VfhZI_7xH8bDgDWJ6juMsb4nfwpxcLvey3VVr8ajrRK6y6uFBw05tAHhS-1G8B1IUFmYpWOCAOEbbcNQWxH7cz7T0eNEUtv1bPluzCKh7QngIXUJ-9rhTKdJWDP3ZYjDm07mQp7J0YB5e3P7BNKpBIw

Ⅲ、将令牌输入

image-20230208191426052

5、使用 dashboard 部署应用

详细步骤请点击👉 使用 dashboard 部署应用.md

五、HELM 部署 EFK

0、相关概念:

  • EFK:CDN(内容分发网络)中的核心技术。分布式日志收集工具

  • 由 ELK ---》 EFK

​ E:(Elasticsearch)搜索引擎,数据索引、切片数据、数据存储

​ L:(Logstash)日志收集,数据收集端

​ K:(Kibana)图形化展示

​ L:(Fluent)日志收集端,资源消耗比 Logstash 低。(使用 HostPath volume ,将 /var/log/containers 进行挂载)

  • EFK 工作原理图

image-20230208193349861

  • 注意:K8S 中,在不同的名字空间中,网络可互相访问,但是资源不可同用

实验步骤:

注意:在实验环境中,需要物理机内存 >= 16G

1、导入所需镜像到私有仓库

先将进行导入到一个节点:

image-20230208194027374

$ docker load -i elasticsearch-oss.tar 
$ docker load -i fluentd-elasticsearch.tar 
$ docker load -i kibanaoss.tar

再更改标签,导入私有仓库:

# 更改标签
$ docker tag docker.elastic.co/elasticsearch/elasticsearch-oss:6.4.2 harbor.yq.com/library/elasticsearch-oss:6.4.2
$ docker tag gcr.io/google-containers/fluentd-elasticsearch:v2.3.2 harbor.yq.com/library/fluentd-elasticsearch:v2.3.2
$ docker tag docker.elastic.co/kibana/kibana-oss:6.4.2 harbor.yq.com/library/kibana/kibana-oss:6.4.2


# 登录
$ docker login harbor.yq.com -u admin -p Harbor1234


# 导入镜像到私有仓库
$ docker push harbor.yq.com/library/elasticsearch-oss:6.4.2
$ docker push harbor.yq.com/library/fluentd-elasticsearch:v2.3.2
$ docker push harbor.yq.com/library/kibana/kibana-oss:6.4.2

2、导入 chart 包,配置部署 Elasticsearch

Ⅰ、实验环境中,避免内存不够用,将 master 节点的污点设置为 PreferNoSchedule

​ 生产环境中,一般不会设置(一般默认的 NoSchedule)

# 查看master01节点的污点
$ kubectl describe node k8s-master01 |grep -i taint
Taints:             node-role.kubernetes.io/master:NoSchedule

# 删除master01的污点
[root@k8s-master01 ~]# kubectl taint node k8s-master01 node-role.kubernetes.io/master=:NoSchedule-

# 设置master01的污点为 PreferNoSchedule
[root@k8s-master01 ~]# kubectl taint node k8s-master01 node-role.kubernetes.io/master=:PreferNoSchedule


# 查看master01节点的污点
[root@k8s-master01 ~]# kubectl describe node k8s-master01 |grep -i taint
Taints:             node-role.kubernetes.io/master:PreferNoSchedule

Ⅱ、导入 chart 包,配置部署 Elasticsearch

导入 chart 包:

image-20230208195951985

$ tar -xf elasticsearch-1.10.2.tgz
$ vim value.yaml

value.yaml 文件需要修改的地方:

image-20230208201313170

部署 Elasticsearch:

$ pwd
/usr/local/kubernetes/helm/efk/elasticsearch

$ kubectl create ns efk
$ helm install --name els1 --namespace=efk -f values.yaml .


# 等待一段时间查看运行状态
$ kubectl get pod -n efk
NAME                                        READY   STATUS    RESTARTS   AGE
els1-elasticsearch-client-9c5cd87c4-fjdhp   1/1     Running   5          18m
els1-elasticsearch-client-9c5cd87c4-lft6l   1/1     Running   0          10m
els1-elasticsearch-data-0                   0/1     Running   1          6m41s
els1-elasticsearch-data-1                   1/1     Running   0          5m15s
els1-elasticsearch-master-0                 1/1     Running   0          7m15s
els1-elasticsearch-master-1                 1/1     Running   1          17m
els1-elasticsearch-master-2                 1/1     Running   0          4m30s

测试 Elasticsearch 组件中的角色:

$ kubectl  run cirror-$RANDOM --rm -it --image=cirros -- /bin/sh

/ # 
/ # curl 10.97.149.187:9200/_cat/nodes
/ # 
172.100.1.158 17 66 16 5.09 10.52  7.50 i  - els1-elasticsearch-client-9c5cd87c4-fjdhp
172.100.0.54  21 99 24 1.58  3.52  2.48 i  - els1-elasticsearch-client-9c5cd87c4-lft6l
172.100.2.47  17 87 10 0.79 12.51 19.84 mi - els1-elasticsearch-master-2
172.100.0.56   6 99 16 1.58  3.52  2.48 di - els1-elasticsearch-data-1
172.100.2.46   6 87 14 0.79 12.51 19.84 di - els1-elasticsearch-data-0
172.100.1.159 20 66 53 5.09 10.52  7.50 mi * els1-elasticsearch-master-1
172.100.0.55  16 99 24 1.58  3.52  2.48 mi - els1-elasticsearch-master-0
/ # 
/ #

3、部署 Fluent

Ⅰ、解压 chart 包,修改 value.yaml 文件:

$ pwd
/usr/local/kubernetes/helm/efk


$ tar -xf fluentd-elasticsearch-2.0.7.tgz 
$ cd fluentd-elasticsearch

# 获取efk的service地址
$ kubectl get svc -n efk
NAME                           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
els1-elasticsearch-client      ClusterIP   10.103.238.205   <none>        9200/TCP   2m56s
els1-elasticsearch-discovery   ClusterIP   None             <none>        9300/TCP   2m56s

$ vim value.yaml

value.yaml 文件需要修改的部分:

image-20230208204625853

Ⅱ、部署 Fluentd:

$ helm install --name flu1 --namespace=efk -f values.yaml .



[root@k8s-master01 fluentd-elasticsearch]# pwd
/usr/local/kubernetes/helm/efk/fluentd-elasticsearch
[root@k8s-master01 fluentd-elasticsearch]# helm install --name flu1 --namespace=efk -f values.yaml .

4、部署 Kibana

Ⅰ、解压 chart 包,修改 value.yaml 文件:

$ pwd
/usr/local/kubernetes/helm/efk

$ tar -xf kibana-0.14.8.tgz
$ cd kibana
$ kubectl get svc -n efk
NAME                           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
els1-elasticsearch-client      ClusterIP   10.97.149.187   <none>        9200/TCP   22m
els1-elasticsearch-discovery   ClusterIP   None            <none>        9300/TCP   22m

$ vim values.yaml

value.yaml 文件修改的部分:

image-20230208220303416

Ⅱ、部署 Kibana:

$ helm install . --name kib1 --namespace=efk -f values.yaml

Ⅲ、修改 Kibana 的 service 类型为 NodePort 暴露出去

$ kubectl get svc -n efk
NAME                           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
els1-elasticsearch-client      ClusterIP   10.97.149.187    <none>        9200/TCP   31m
els1-elasticsearch-discovery   ClusterIP   None             <none>        9300/TCP   31m
kib1-kibana                    ClusterIP   10.104.196.171   <none>        443/TCP    4m35s


$ kubectl edit svc kib1-kibana -n efk

image-20230208220932041

5、浏览器访问测试

Ⅰ、先运行一个控制器,访问,产生日志

$ kubectl create deployment myapp --image=wangyanglinux/myapp:v1
$ kubectl scale deployment myapp --replicas=5

$ kubectl create svc clusterip myapp --tcp=80:80
$ kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   29d
myapp        ClusterIP   10.103.114.252   <none>        80/TCP    5s

$ while true;do curl 10.103.114.252/hostname.html ;sleep 1;done

Ⅱ、浏览器访问测试

先查询 Kibana 的 service 地址:

[root@k8s-master01 elasticsearch]# kubectl get svc -n efk |grep kib
kib1-kibana                    NodePort    10.104.196.171   <none>        443:31355/TCP   19m

浏览器访问:

image-20230208222459636

image-20230208222547829

image-20230209031042933

image-20230209031113865

image-20230209031322127

六、HELM 部署Prometheus

0、相关概念

Prometheus:开源的报警系统和监控工具包,一种时序数据库,按照时间序列记录数据( PQL 语句)

  • 监控服务器对比:

image-20230209090100470

  • Operator 开发框架

​ CRD+自定义控制器,组成新的开发方向

  • Prometheus-Operator 的一些组件

1.MetricServer:对接 Prometheus ,从其中获取数据,再给集群内使用( 如:kubectl、hpa、schedule)

2.PrometheusOperator:系统监测,警报工具箱,用于存储监控数据

3.NodeExporter:存在于每个节点,对接猫头鹰监控。用于各节点关键度量指标状态数据

4.KubernetesMetics:收集集群内资源对象数据,指定报警规则

5.Prometheus:采用 pull 方式收集 ApiServer、Schedule、Controller Manager、kubelet组件的数据,通过http传输

6.Grafana:图形化展示工具

  • Prometheus 的工作原理图

image-20230209091113572

  • 猫头鹰监控:(谷歌开发的),部署在物理节点追踪,实现对容器的资源使用量进行监控,每个节点的 Kubelet 自带了猫头鹰监控的功能

  • Prometheus 能够实现动态发现(Consul)

Operator部署:

1、导入镜像

image-20230209093236860

# 解压镜像压缩包,导入镜像,导入私有仓库
$ pwd
/usr/local/kubernetes/prometheus

$ tar -xf prometheus.tar.gz
$ cd prometheus


$ docker load -i addon-resizer.tar 
Loaded image: k8s.gcr.io/addon-resizer:1.8.4
$ docker tag k8s.gcr.io/addon-resizer:1.8.4 harbor.yq.com/library/addon-resizer:1.8.4
$ docker push harbor.yq.com/library/addon-resizer:1.8.4

$ docker load -i alertmanager.tar 
Loaded image: quay.io/prometheus/alertmanager:v0.18.0
$ docker tag quay.io/prometheus/alertmanager:v0.18.0 harbor.yq.com/library/alertmanager:v0.18.0
$ docker push harbor.yq.com/library/alertmanager:v0.18.0

$ docker load -i configmap-reload.tar 
Loaded image: quay.io/coreos/configmap-reload:v0.0.1
$ docker tag quay.io/coreos/configmap-reload:v0.0.1 harbor.yq.com/library/configmap-reload:v0.0.1
$ docker push harbor.yq.com/library/configmap-reload:v0.0.1

$ docker load -i grafana.tar 
Loaded image: grafana/grafana:6.2.2
$ docker tag grafana/grafana:6.2.2 harbor.yq.com/library/grafana:6.2.2
$ docker push harbor.yq.com/library/grafana:6.2.2

$ docker load -i k8s-prometheus-adapter-amd64.tar 
Loaded image: quay.io/coreos/k8s-prometheus-adapter-amd64:v0.4.1
$ docker tag quay.io/coreos/k8s-prometheus-adapter-amd64:v0.4.1 harbor.yq.com/library/k8s-prometheus-adapter-amd64:v0.4.1
$ docker push harbor.yq.com/library/k8s-prometheus-adapter-amd64:v0.4.1The push refers to repository 

$ docker load -i kube-rbac-proxy.tar 
Loaded image: quay.io/coreos/kube-rbac-proxy:v0.4.1
$ docker tag quay.io/coreos/kube-rbac-proxy:v0.4.1 harbor.yq.com/library/kube-rbac-proxy:v0.4.1
$ docker push harbor.yq.com/library/kube-rbac-proxy:v0.4.1

$ docker load -i kube-state-metrics.tar 
Loaded image: quay.io/coreos/kube-state-metrics:v1.7.1
$ docker tag quay.io/coreos/kube-state-metrics:v1.7.1 harbor.yq.com/library/kube-state-metrics:v1.7.1
$ docker push harbor.yq.com/library/kube-state-metrics:v1.7.1

$ docker load -i node-exporter.tar 
Loaded image: quay.io/prometheus/node-exporter:v0.18.1
$ docker tag quay.io/prometheus/node-exporter:v0.18.1 harbor.yq.com/library/node-exporter:v0.18.1
$ docker push harbor.yq.com/library/node-exporter:v0.18.1

$ docker load -i prometheus-config-reloader.tar 
Loaded image: quay.io/coreos/prometheus-config-reloader:v0.31.1
$ docker tag quay.io/coreos/prometheus-config-reloader:v0.31.1 harbor.yq.com/library/prometheus-config-reloader:v0.31.1
$ docker push harbor.yq.com/library/prometheus-config-reloader:v0.31.1

$ docker load -i prometheus-operator.tar 
Loaded image: quay.io/coreos/prometheus-operator:v0.31.1
$ docker tag quay.io/coreos/prometheus-operator:v0.31.1 harbor.yq.com/library/prometheus-operator:v0.31.1
$ docker push harbor.yq.com/library/prometheus-operator:v0.31.1

$ docker load -i prometheus.tar 
Loaded image: quay.io/prometheus/prometheus:v2.11.0
$ docker tag quay.io/prometheus/prometheus:v2.11.0 harbor.yq.com/library/prometheus:v2.11.0
$ docker push harbor.yq.com/library/prometheus:v2.11.0

2、导入 Operator 框架部署的压缩包

image-20230209093150855

$ tar -xf kube-prometheus.git.tar.gz
$ cd kube-prometheus/manifests/
$ pwd
/usr/local/kubernetes/prometheus/kube-prometheus/manifests



# 修改 yaml 文件中镜像下载位置,指向私有仓库
# (由于 yaml 文件很多,写个脚本筛选,再对应修改)
$ vim /usr/local/bin/check 
$ cat /usr/local/bin/check
#!/bin/bash
for i in $(ls)
do
  cat $i|grep "image" > /dev/null
  [ $? -eq 0 ] && echo $i || echo "" > /dev/null
done

$ chmod a+x /usr/local/bin/check
$ check 
0prometheus-operator-0alertmanagerCustomResourceDefinition.yaml
0prometheus-operator-0prometheusCustomResourceDefinition.yaml
0prometheus-operator-deployment.yaml
grafana-dashboardDefinitions.yaml
grafana-deployment.yaml
kube-state-metrics-deployment.yaml
node-exporter-daemonset.yaml
prometheus-adapter-deployment.yaml
prometheus-rules.yaml


$ vim 0prometheus-operator-deployment.yaml
$ cat 0prometheus-operator-deployment.yaml |grep image
        - --config-reloader-image=harbor.yq.com/library/configmap-reload:v0.0.1
        image: harbor.yq.com/library/prometheus-operator:v0.31.1
$ vim grafana-deployment.yaml
$ cat grafana-deployment.yaml|grep image
      - image: harbor.yq.com/library/grafana:6.2.2
$ vim kube-state-metrics-deployment.yaml
$ cat kube-state-metrics-deployment.yaml |grep image
        image: harbor.yq.com/library/kube-rbac-proxy:v0.4.1
        image: harbor.yq.com/library/kube-rbac-proxy:v0.4.1
        image: harbor.yq.com/library/kube-state-metrics:v1.7.1
        image: harbor.yq.com/library/addon-resizer:1.8.4
$ vim node-exporter-daemonset.yaml
$ cat node-exporter-daemonset.yaml |grep image
        image: harbor.yq.com/library/node-exporter:v0.18.1
        image: harbor.yq.com/library/kube-rbac-proxy:v0.4.1
$ vim prometheus-adapter-deployment.yaml
$ cat prometheus-adapter-deployment.yaml |grep image
        image: harbor.yq.com/library/k8s-prometheus-adapter-amd64:v0.4.1

3、修改 yaml 文件

修改 grafana-service.yaml 文件,使用 nodepode 方式访问 grafana:

$ vim grafana-service.yaml                           
    apiVersion: v1
    kind: Service
    metadata:
      name: grafana
      namespace: monitoring
    spec:
      type: NodePort      #添加内容
      ports:
      - name: http
        port: 3000
        targetPort: http
        nodePort: 30100   #添加内容
      selector:
        app: grafana

修改 prometheus-service.yaml,改为 nodepode

$ vim prometheus-service.yaml              
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        prometheus: k8s
      name: prometheus-k8s
      namespace: monitoring
    spec:
      type: NodePort
      ports:
      - name: web
        port: 9090
        targetPort: web
        nodePort: 30200
      selector:
        app: prometheus
        prometheus: k8s

修改 alertmanager-service.yaml,改为 nodepode

vim alertmanager-service.yaml 
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        alertmanager: main
      name: alertmanager-main
      namespace: monitoring
    spec:
      type: NodePort
      ports:
      - name: web
        port: 9093
        targetPort: web
        nodePort: 30300
      selector:
        alertmanager: main
        app: alertmanager

4、部署:

多次执行命令,基于所有 yaml 文件运行资源对象

$ kubectl apply -f ../manifests/

5、查看资源对象运行状态:

$ kubectl get pod -n monitoring
NAME                                  READY   STATUS    RESTARTS   AGE
alertmanager-main-0                   2/2     Running   0          110s
alertmanager-main-1                   1/2     Running   0          31s
grafana-58c655bb57-8nfzx              1/1     Running   0          2m
kube-state-metrics-698b8547bc-zpht5   4/4     Running   0          104s
node-exporter-bjgk2                   2/2     Running   0          118s
node-exporter-ddrq6                   2/2     Running   0          118s
node-exporter-vrmh7                   2/2     Running   0          118s
prometheus-adapter-5cf4f7d66f-gtdsd   1/1     Running   0          119s
prometheus-k8s-0                      3/3     Running   1          99s
prometheus-k8s-1                      3/3     Running   1          99s
prometheus-operator-97fc48778-crbhh   1/1     Running   0          2m


$ kubectl get svc -n monitoring
NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
alertmanager-main       NodePort    10.100.148.232   <none>        9093:30300/TCP      105s
alertmanager-operated   ClusterIP   None             <none>        9093/TCP,6783/TCP   2m6s
grafana                 NodePort    10.101.181.149   <none>        3000:30100/TCP      2m16s
kube-state-metrics      ClusterIP   None             <none>        8443/TCP,9443/TCP   2m16s
node-exporter           ClusterIP   None             <none>        9100/TCP            2m16s
prometheus-adapter      ClusterIP   10.110.84.17     <none>        443/TCP             2m15s
prometheus-k8s          NodePort    10.100.189.1     <none>        9090:30200/TCP      2m14s
prometheus-operated     ClusterIP   None             <none>        9090/TCP            116s
prometheus-operator     ClusterIP   None             <none>        8080/TCP  

6、浏览器访问

image-20230209104211539

image-20230209104223291

image-20230209104231384

7、Grafana 监控

登录导入

image-20230209104601012

image-20230209104631623

image-20230209104842717

image-20230209104911914

image-20230209104934067

image-20230209105026805

image-20230209105139876

监控

image-20230209105237417

image-20230209105404690

image-20230209105436065

七、自动扩容缩

​ MeticServer 对接 Prometheus ,获取资源消耗信息

​ 结合资源消耗信息,hpa控制器,实现自动扩容缩

注意:扩容相应迅速、但是收缩很慢

# MeticServer 对接 Prometheus 后,kubectl top 命令可用
$ kubectl top node              # 查看node资源消耗
$ kubectl top pod               # 查看pod资源消耗

1、上传导入镜像

hpa镜像是专门对hpa自动扩容缩,进行测试的镜像

image-20230209181152155

# 导入镜像到本地
$ docker load -i hpa.tar 
Loaded image: wangyanglinux/hpa:latest

# 登录私有仓库
$ docker login harbor.yq.com -u admin -p Harbor12345

# 修改镜像标签,导入私有镜像仓库
$ docker tag wangyanglinux/hpa:latest harbor.yq.com/library/hpa:v1
$ docker push harbor.yq.com/library/hpa:v1

2、创建 deployment 控制器,和对应的 service

HPA 可以根据 CPU 利用率自动伸缩 RC、Deployment、RS 中的 Pod 数量

# 方法一:用命令创建deployment控制器,service
$ kubectl run php-apache --image=harbor.yq.com/library/hpa:v1 --requests=cpu=200m --expose --port=80



# 方法二:也可以通过干跑,导出 yaml 文件,基于 yaml 文件启动
$ mkdir 10;cd 10
$ kubectl run php-apache --image=harbor.yq.com/library/hpa:v1 --requests=cpu=200m --expose --port=80 --dry-run -o yaml > 3.hpa.yaml
$ cat 3.hpa.yaml 
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  name: php-apache
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: php-apache
status:
  loadBalancer: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    run: php-apache
  name: php-apache
spec:
  replicas: 1
  selector:
    matchLabels:
      run: php-apache
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        run: php-apache
    spec:
      containers:
      - image: harbor.yq.com/library/hpa:v1
        name: php-apache
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 200m
status: {}

$ kubectl apply -f 3.hpa.



# 创建完成后,查看运行状态
$ kubectl get deployment
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
php-apache   1/1     1            1           56s

$ kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   30d
php-apache   ClusterIP   10.110.178.169   <none>        80/TCP    58s

3、创建 HPA 控制器

$ kubectl autoscale deployment php-apache --cpu-percent=50 --min=2 --max=10

# 等待一会后,hpa控制器对资源使用,进行查看
$ kubectl get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   0%/50%    2         10        2          117s

4、增加负载,查看负载节点数目

$ kubectl run -i --tty work --rm --image=busybox /bin/sh
    while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done




# 等待一段时间后,自动扩容了(扩容迅速)
$ kubectl get pod |grep php-apache|wc -l
10

$ kubectl get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   65%/50%   2         10        10         9m59s


# 退出测试的pod以后,需要等待一段时间才会缩容(缩容缓慢)

八、资源限制

​ MeticServer 有了获取资源消耗情况的能力,可以对资源对象,使用的资源,进行限制

1、资源限制 - Pod

使用 cgroup 实现资源限制(控制组,内核技术):Kubernetes 对资源的限制实际上是通过 CGROUP 来控制的,CGROUP 是容器的一组用来控制内核如果运行进程的相关属性集合。针对内存、CPU、和各种设备都有对应的 CGROUP

若不对pod进行资源限制,默认情况下,pod能使用集群中所有的资源

spec.containers.resources.limits 最高请求值(硬限制)

spec.containers.resouces.requests 分配值(软限制)

spec:
  containers:
  - image: wangyanglinux/myapp:v1
    name: auth
    resources:
      limits:
        cpu: "4"
        memory: 2Gi
      requests:
        cpu: 250m
        memory: 250Mi

requests 要分配的资源,limits 为最高请求的资源,可以理解为初始值和最大值

注意:若limits 和 requests 的值设置为相同,那么在资源请求中,优先分配

资源分配优先级: limits 与 requests 值设置为相同 > request 与limits 存在 > 无资源限制

一般情况下的 limits 值与 requests 值的设置:使用工具进行压测后,获取的值设置为 requests,requests 值 / 0.8 为 limits 的值

2、资源限制 - 名称空间

一、计算资源配额

apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-resources
  namespace: spark-cluster
spec:
  hard:
    requests.cpu: "20"
    requests.memory: 100Gi
    limits.cpu: "40"
    limits.memory: 200Gi

二、配置对象数量配额限制

apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-counts
  namespace: spark-cluster
spec:
  hard:
    pods: "20"
    configmaps: "10"
    persistentvolumeclaims: "4"
    replicationcontrollers: "20"
    secrets: "10"
    services: "10"
    services.loadbalancers: "2"

三、配置 CPU 和 内存 limitrange

apiVersion: v1
kind: LimitRange
metadata:
  name: mem-limit-range
  namespace: example
spec:
  limits:
  - default:  # 默认限制值
      memory: 512Mi
      cpu: 2
    defaultRequest:  # 默认请求值
      memory: 256Mi
      cpu: 0.5
    max:  # 最大的资源限制
      memory: 800Mi
      cpu: 3
    min:  # 最小限制
      memory: 100Mi
      cpu: 0.3
    maxLimitRequestRatio:  # 超售值(提升资源使用率)(值越大,使用率越高;但是稳定性越低)
      memory: 2
      cpu: 2
    type: Container # Container / Pod / PersistentVolumeClaim

3、在 dev 名字空间中测试 pod 限制

​ dev名字空间是在集群安全中,创建的名字空间,管理员为 devuser

1)创建 resourcequota 资源对象

​ 对 dev名字空间中的pod个数,进行限制

[root@k8s-master01 10]# vim 4.rq.yaml
[root@k8s-master01 10]# cat 4.rq.yaml 
apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-counts
  namespace: dev
spec:
  hard:
    pods: "4"
[root@k8s-master01 10]# kubectl apply -f 4.rq.yaml 

2)进入 devuser 用户,测试限制

[root@k8s-master01 10]# su - devuser
[devuser@k8s-master01 ~]$ kubectl get pod 
No resources found.

# 创建deployment控制器
[devuser@k8s-master01 ~]$ kubectl create deployment myapp --image=harbor.yq.com/library/myapp:v1
deployment.apps/myapp created

# 修改副本数为10个
[devuser@k8s-master01 ~]$ kubectl scale deployment myapp --replicas=10
deployment.extensions/myapp scaled


# 一段时间后,副本数仍然为4个,pods限制生效
[devuser@k8s-master01 ~]$ kubectl get pod 
NAME                     READY   STATUS    RESTARTS   AGE
myapp-65d7d4c559-5qp5c   1/1     Running   0          3m4s
myapp-65d7d4c559-6mmpf   1/1     Running   0          3m20s
myapp-65d7d4c559-b9zth   1/1     Running   0          3m4s
myapp-65d7d4c559-wrlrr   1/1     Running   0          3m4s