k8s阶段05 Operator, DaemonSet, Job, CronJob, Ingress和Ingress Controller(蓝绿/恢复发布), helm

StatefulSet:编排有状态应用

基本要求:
    需要给每个实例惟一且固定的标识,依赖于一个专用的Headless Service; 
    需要给每个实例一个专用的PVC卷,该卷要来自volumeTemplateClaim,卷的标识 “template_name-pod_name”;
    
Pod Management Policy: 
    OrderedReady:按顺序,依次
    Parallel:并行
    
StatefulSet仅负责为有状态应用的编排,提供一个基础框架;

Operator

Operator Framework:    #go开发框架
    声明式API

    自定义的资源类型:
        外置、独立的API Server; #通过k8s的api server调到自己开发的API Server
        CRD: #K8S里自定义资源类型
    自定义Controller #自己开发控制器
    
    基于专用的Operator编排运行某有状态应用的逻辑:
        1、部署Operator及其专用的资源类型;
        2、使用专用的资源类型,来声明一个有状态应用的编排需求;

#社区中心网站
https://operatorhub.io/

#示例(通过Operator安装es)
#参考文档: https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-deploy-eck.html
#1.部署crd (就会拥有crd资源对象)
[root@master01 ~]#kubectl create -f https://download.elastic.co/downloads/eck/2.15.0/crds.yaml
#查看crd
[root@master01 ~]#kubectl get crd
#生成的资源类型
[root@master01 ~]#kubectl explain Elasticsearch

#2.基于RBAC规则部署operator (也就是执行上面资源对象的控制器)
[root@master01 ~]#kubectl apply -f https://download.elastic.co/downloads/eck/2.15.0/operator.yaml
[root@master01 ~]#kubectl get pods -n elastic-system 
NAME                 READY   STATUS    RESTARTS   AGE
elastic-operator-0   1/1     Running   0          91s

#3.定义es集群(注意内存,每个节点4g)
[root@master01 eck-operator]#vim elasticsearch-myes-cluster.yaml
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: 
  namespace: mall
spec:
  version: 8.13.0 #es集群版本
  nodeSets: #每个实例设定
  - name: default #这个配置叫default
    count: 3
    config:
      node.store.allow_mmap: false #是否启用内存映射
    volumeClaimTemplates: #卷请求模板
    - metadata:
        name: elasticsearch-data
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 5Gi
       #storageClassName: nfs-csi
        storageClassName: openebs-hostpath #存储类
[root@master01 eck-operator]#kubectl create namespace  mall
#会创建pod,service,statefulset
[root@master01 eck-operator]#kubectl apply -f elasticsearch-myes-cluster.yaml
[root@master01 eck-operator]#kubectl get all -n mall
NAME                    READY   STATUS    RESTARTS   AGE
pod/myes-es-default-0   1/1     Running   0          18m
pod/myes-es-default-1   1/1     Running   0          18m
pod/myes-es-default-2   1/1     Running   0          18m

NAME                            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/myes-es-default         ClusterIP   None             <none>        9200/TCP   18m
service/myes-es-http            ClusterIP   10.106.251.132   <none>        9200/TCP   18m
service/myes-es-internal-http   ClusterIP   10.107.141.153   <none>        9200/TCP   18m
service/myes-es-transport       ClusterIP   None             <none>        9300/TCP   18m

NAME                               READY   AGE
statefulset.apps/myes-es-default   3/3     18m

#获取es首次登陆密码
[root@master01 eck-operator]#kubectl get secret -n mall
myes-es-elastic-user                 Opaque   1      24m
[root@master01 eck-operator]#kubectl get secret myes-es-elastic-user -o yaml -n mall
  elastic: MTdZMU1YN2RNOG4zcDlWeFRmcjA4TGEw
#base64解码
]#echo MTdZMU1YN2RNOG4zcDlWeFRmcjA4TGEw | base64 -d
17Y1MX7dM8n3p9VxTfr08La0
#访问es服务(通过service/myes-es-http服务)
]#curl -u "elastic:17Y1MX7dM8n3p9VxTfr08La0" -k https://10.106.251.132:9200
#也可生成一个交互式pod来访问,这样可以通过服务名地址访问
]#kubectl run client-$RANDOM --image ikubernetes/admin-box:v1.2 -it --rm --restart=Never --command -- /bin/bash
root@client-17621 /# curl -u "elastic:17Y1MX7dM8n3p9VxTfr08La0" -k https://myes-es-http.mall:9200

#定义kibana
[root@master01 eck-operator]#vim kibana-myes.yaml
apiVersion: kibana.k8s.elastic.co/v1
kind: Kibana
metadata:
  name: kibana
  namespace: mall
spec:
  version: 8.13.0
  count: 1
  elasticsearchRef: #应用es集群名
    name: "myes"
  http:
    tls: #使用tls通讯
      selfSignedCertificate:
        disabled: true
    service:
      spec:
        type: LoadBalancer
#会创建kibana的pod,deployment和service
[root@master01 eck-operator]#kubectl apply -f kibana-myes.yaml
#直接有一个kibana的资源对象 (当前为red是因为要下载pod并运行)
[root@master01 eck-operator]#kubectl get kibana -n mall
NAME     HEALTH   NODES   VERSION   AGE
kibana   red              8.13.0    25s
[root@master01 eck-operator]#kubectl get all -n mall
NAME                            READY   STATUS    RESTARTS   AGE
pod/kibana-kb-dfc656fdc-snrth   1/1     Running   0          6m
...
NAME                            TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/kibana-kb-http          LoadBalancer   10.97.83.49      10.0.0.53     5601:31706/TCP   6m
...
#浏览器输入,访问kibana,用户名/密码:elastic/17Y1MX7dM8n3p9VxTfr08La0
10.0.0.53:5601

#定义filebeat(上面Operator创建crd已包含filebeat)
[root@master01 eck-operator]#vim beats-filebeat.yaml
apiVersion: beat.k8s.elastic.co/v1beta1
kind: Beat
metadata:
  name: filebeat
  namespace: mall #把整个文件中的namespace都改成mall,下面还有
spec:
  type: filebeat
  version: 8.13.0
  elasticsearchRef: #引用的es
    name: "myes"
  kibanaRef: #引用的kibana
    name: "kibana"
... #下面有排除一些名称空间下的pod(和系统有关,防止敏感信息泄露)
#会用daemonset部署filebeat
[root@master01 eck-operator]#kubectl apply -f beats-filebeat.yaml
#会有filebeat的资源类型
[root@master01 eck-operator]#kubectl get beat -n mall
NAME       HEALTH   AVAILABLE   EXPECTED   TYPE       VERSION   AGE
filebeat   red                  3          filebeat             37s
#查看daemonset
[root@master01 eck-operator]#kubectl get ds -n mall

#扩容,升级等操作只要修改配置文件并应用即可,升级会用内置的滚动更新策略,eck operator 会自动完成

 

3 DaemonSet

#DaemonSet用于确保所有或选定的工作节点上都运行有一个Pod副本
DaemonSet:编排系统级应用   
    资源规范:
        selector: {}
        template:{}
   
    系统级存在共享宿主信息或资源需要:
        1、hostNet/hostPid/hostUser
        2、hostPath volume 
   
    更新:
        updateStrategy
            rollingUpdate: #默认滚动更新
                maxSurge    #默认0,一般都设置为0,否则就有2个冲突了
                maxUnavailable #默认1
        #默认如下设定,也比较合理        
        updateStrategy:
            rollingUpdate:
                maxSurge: 0
                maxUnavailable: 1
            type: RollingUpdate
                
#示例
[root@master01 daemonsets]#vim daemonset-demo.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: daemonset-demo
  namespace: prom
  labels:
    app: prometheus
    component: node-exporter
spec:
  selector:
    matchLabels:
      app: prometheus
      component: node-exporter
  template:
    metadata:
      name: prometheus-node-exporter
      labels:
        app: prometheus
        component: node-exporter
    spec:
      containers:
      - image: prom/node-exporter:v1.5.0
        name: prometheus-node-exporter
        ports:
        - name: prom-node-exp
          containerPort: 9100
          hostPort: 9100
        livenessProbe:
          tcpSocket:
            port: prom-node-exp
          initialDelaySeconds: 3
        readinessProbe:
          httpGet:
            path: '/metrics'
            port: prom-node-exp
            scheme: HTTP
          initialDelaySeconds: 5
      hostNetwork: true #共享宿主机网络
      hostPID: true
[root@master01 daemonsets]#kubectl create namespace prom
[root@master01 daemonsets]#kubectl apply -f daemonset-demo.yaml -n prom
#查看(这里3个是因为集群节点3个)
[root@master01 daemonsets]#kubectl get ds -n prom
NAME             DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
daemonset-demo   3         3         0       3            0           <none>          58s
[root@master01 daemonsets]#kubectl get ds -n prom -o wide
NAME             DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE    CONTAINERS                 IMAGES                      SELECTOR
daemonset-demo   3         3         3       3            3           <none>          101s   prometheus-node-exporter   prom/node-exporter:v1.5.0   app=prometheus,component=node-exporter
#查看pod(因为共享宿主机网络,所以ip显示的是节点地址)
[root@master01 daemonsets]#kubectl get pods -n prom -o wide
NAME                   READY   STATUS    RESTARTS   AGE     IP           NODE     NOMINATED NODE   READINESS GATES
daemonset-demo-cfdbq   1/1     Running   0          5m24s   10.0.0.154   node03   <none>           <none>
daemonset-demo-nggp7   1/1     Running   0          5m24s   10.0.0.152   node01   <none>           <none>
daemonset-demo-zhqrd   1/1     Running   0          5m24s   10.0.0.153   node02   <none>           <none>
#查看随便一台的指标
[root@master01 daemonsets]#curl 10.0.0.154:9100/metrics

#升级
[root@master01 daemonsets]#vim daemonset-demo.yaml
...
    spec:
      containers:
      - image: prom/node-exporter:v1.6.0 #修改版本
#更新
[root@master01 daemonsets]#kubectl apply -f daemonset-demo.yaml
#可以看到是逐一更新的
]#kubectl get pods -n prom -w

 

5 Job和CronJob

#一次性任务用job,周期性任务用cronjob
#本质是cronjob是不断创建一个新job来实现
#注:Job和CronJob类型重启策略应该设置为OnFailure或Never,OnFailure最合适(可设重启次数,默认6)

#有时候有些服务pod会使用job来做环境初始化

Job控制器的应用编排机制

Job负责编排运行有结束时间的“一次性”任务,而前面的Deployment和DaemonSet主要负责编排始终运行的守护进程类应用;
  ◼ 控制器要确保Pod内的进程“正常(成功完成任务)”地退出
  ◼ 非正常退出的Pod可以根据需要重启,并在重试一次的次数后终止
  ◼ 有些Job是单次任务,也有些Job需要运行多次(次数通常固定)
  ◼ 有些任务支持同时创建及并行运行多个Pod以加快任务处理速度,Job控制器还允许用户自定义其并行度
  
需要周期性运行的Job,则由CronJob控制器负责编排
  ◼ CronJob建立在Job的功能之上,是更高层级的控制器
  ◼ 它以Job控制器完成单批次的任务编排,而后为这种Job作业提供需要运行的周期定义

Job资源规范

 Job资源同样需要标签选择器和Pod模板,但它不需要指定replicas,而是应该给定completions,即需要完成的作业数,默认为1次;
  ◼ Job资源会为其Pod对象自动添加“job-name=JOB_NAME”和“controller-uid=UID”标签,并使用标签选择器完成对controller-uid标签的关联,因此,selector并非必选字段
  ◼ Pod的命名格式:`$(job-name)-$(index)-$(random-string),其中的$(index)字段取值与completions和completionMode有关
  ◼ 注意
    ◆ Job资源所在群组为“batch/v1”
    ◆ Job资源中,Pod的RestartPolicy的取值
      只能为Never或OnFailure

#示例模板
apiVersion: batch/v1 # API群组及版本;
kind: Job # 资源类型特有标识;
metadata:
 name <string> # 资源名称,在作用域中要惟一;
 namespace <string> # 名称空间;Job资源隶属名称空间级别;
spec:
 selector <object> # 标签选择器,必须匹配template字段中Pod模板中的标签;(可不设,Job自动生成标签够用)
 suspend <boolean> # 是否挂起当前Job的执行,挂起作业会重置StartTime字段的值;
 template <object> # Pod模板对象;
 completions <integer> #期望的成功完成的作业次数,成功运行结束的Pod数量;(要运行几次)
 completionMode <string> # 追踪Pod完成的模式,支持Indexed和NonIndexed(默认)两种;
 ttlSecondsAfterFinished <integer> # 终止状态作业的生存时长,超期将被删除;
 parallelism <integer> # 作业的最大并行度,默认为1;(不超过completions运行次数,否则无意义)
 backoffLimit <integer> # 将作业标记为“Failed”之前的重试次数,默认为6;
 activeDeadlineSeconds <integer> # 作业启动后可处于活动状态的时长;

Job的状态

#下面模拟一个简单Job(串行运行)
[root@master01 jobs_and_cronjobs]#vim job-demo.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: job-demo
spec:
  template:
    spec:
      containers:
      - name: myjob
        image: ikubernetes/admin-box:v1.2
        imagePullPolicy: IfNotPresent
        command: ["/bin/sh", "-c", "sleep 15"] #执行命令
      restartPolicy: Never
  completions: 2 #要运行2次
  ttlSecondsAfterFinished: 3600
  backoffLimit: 3
  activeDeadlineSeconds: 300
#运行并观察,启动一个完成后再启动一个
]#kubectl apply -f job-demo.yaml && kubectl get pods -w
#完成后查看pods,都是Completed状态
[root@master01 ~]#kubectl get pods
NAME                       READY   STATUS      RESTARTS        AGE
job-demo-2rpxh             0/1     Completed   0               114s
job-demo-ct2xk             0/1     Completed   0               38s
#查看job
[root@master01 jobs_and_cronjobs]#kubectl get jobs -o wide

#下面模拟一个简单Job(并行运行)
[root@master01 jobs_and_cronjobs]#vim job-para-demo.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: job-para-demo
spec:
  template:
    spec:
      containers:
      - name: myjob
        image: ikubernetes/admin-box:v1.2
        imagePullPolicy: IfNotPresent
        command: ["/bin/sh", "-c", "sleep 15"]
      restartPolicy: Never
  completions: 6 #运行6次
  parallelism: 2 #并行数改为2
  ttlSecondsAfterFinished: 3600
  backoffLimit: 3
  activeDeadlineSeconds: 1200
#运行,同一时间有2个pod执行,至于在哪个节点上是调度器决定的
[root@master01 jobs_and_cronjobs]#kubectl apply -f job-para-demo.yaml &&kubectl get pods -w

#job一般不存在更新的需求

CronJob

#每隔一段时间根据job模板创建job
  CronJob控制器用于管理Job资源的运行时间,它允许用户在特定的时间或以指定的间隔运行Job
  CronJob控制器的功能类似于linux操作系统的周期性任务作业计划(crontab),用于控制作业运行的时间点及周期性运行的方式:
    ◼ 仅在未来某时间点将指定的作业运行一次
    ◼ 在指定的周期性时间点重复运行指定的作业
  CronJob资源也是标准的API资源类型
  注意:
    ◼ 在CronJob中,通配符“?”和“*”的意义相同,它们都表示任何可用的有效值

#示例模板
apiVersion: batch/v1 # API群组及版本;
kind: CronJob # 资源类型特有标识;
metadata:
 name <string> # 资源名称,在作用域中要惟一;
 namespace <string> # 名称空间;CronJob资源隶属名称空间级别;
spec:
 jobTemplate <Object> # job作业模板,必选字段;
  metadata <object> # 模板元数据;
  spec <object> # 作业的期望状态;
 schedule <string> # 调度时间设定,必选字段;
 #前一job没结束,后一job开始了,允许吗?allow允许,forbid禁止,Replace替换(后job替换前job)
 concurrencyPolicy <string> # 并发策略,可用值有Allow、Forbid和Replace;
 failedJobsHistoryLimit <integer> # 失败作业的历史记录数,默认为1;
 successfulJobsHistoryLimit <integer> # 成功作业的历史记录数,默认为3;
 startingDeadlineSeconds <integer> #因错过时间点而未执行的作业的可超期时长;(因快到下一个执行点了)
 suspend <boolean> # 是否挂起后续的作业,不影响当前作业,默认为false;

#Cronjob说明:
#每两小时执行一次
0 */2 * * * #分钟不能用*,不然就会变成没隔2小时每分钟执行
0 7,10,16 * * * #7,10,16点各执行一次
0 8-18 * * * #8点到18点,每小时执行一次

#示例
[root@master01 jobs_and_cronjobs]#vim cronjob-demo.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: cronjob-demo
  namespace: default
spec:
  schedule: "* * * * *" #每分钟执行一次
  jobTemplate:
    metadata:
      labels: #标签加不加都可以
        controller: cronjob-demo
    spec:
      parallelism: 1 #并行度为1
      completions: 1 #运行1次
      ttlSecondsAfterFinished: 600
      backoffLimit: 3
      activeDeadlineSeconds: 60
      template:
        spec:
          containers:
          - name: myjob
            image: ikubernetes/admin-box:v1.2
            command:
            - /bin/sh
            - -c
            - date; echo Hello from CronJob, sleep a while...; sleep 10
          restartPolicy: OnFailure
  startingDeadlineSeconds: 300
[root@master01 jobs_and_cronjobs]#kubectl apply -f cronjob-demo.yaml
#查看,每分钟会执行job (job和pod保留最近3个,设置可改)
[root@master01 jobs_and_cronjobs]#kubectl get cronjob,job,pods
NAME                         SCHEDULE    TIMEZONE   SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/cronjob-demo   * * * * *   <none>     False     0        31s             44s

NAME                              STATUS     COMPLETIONS   DURATION   AGE
job.batch/cronjob-demo-28882640   Complete   1/1           13s        31s

NAME                              READY   STATUS      RESTARTS       AGE
pod/cronjob-demo-28882640-llz5p   0/1     Completed   0              31s
#查看日志,里面会显示几点执行的
[root@master01 jobs_and_cronjobs]#kubectl logs cronjob-demo-28882640-llz5p
Sat Nov 30 09:20:00 UTC 2024
Hello from CronJob, sleep a while...

#避免一直运行,这里删除cronjob,对应的job和pod也会被删除
[root@master01 jobs_and_cronjobs]#kubectl delete -f cronjob-demo.yaml

 

1 Ingress和Ingress Controller

将服务类应用暴露至集群外部的方法:
    NodePort Service 
    LoadBalancer Service 
        使用专用NodePort来暴露服务
    Service with ExternalIP 
        使用专用的ExternalIP来暴露服务
       
以上四层代理
通过 Ingress + Ingress Controller 转为七层代理,统一管理流量
#Ingress Controller直接把请求打到service下的pod上,进行负载均衡(不需要service负载均衡了)。
#service的负载均衡功能不需要了,但是需要pod发现功能,把pod信息发给Ingress Controller

Ingress及其它相关的资源类型 + Ingress Controller 
    资源类型: 
        Ingress 
        IngressClass #告诉哪个Ingress Controller可以加载解析Ingress资源
        IngressGateway #更高阶的功能,流量网关,业务网关(目前属于alpha特性,后续版本会提供)
        
    Ingress Controller: #有如下几种可以选择
        Ingress-Nginx: kubernetes-sigs #用的最多
            registry.k8s.io 
        Kong       
        Traefik #用的较多
        Contour
        Gloo
        Cilium  
        #各主流Ingress Controller对比图:
        https://blog.palark.com/wp-content/uploads/2019/10/kubernetes-ingress-comparison.png
        
七层代理多个服务的方式:
    虚拟主机:
        port
        ip 
        host: 基于主机名的虚拟主机
    基于单一虚拟主机开放多服务:
        scheme://host:port/PATH{1,2,3, ...}
    最终可用的方式:基于主机名的虚拟主机;
    SSL虚拟主机:SNI
    
    Ingress的类型: 
        简单扇出:基于单一虚拟主机使用不同的Path开放多服务  
          http://magedu.com/blog/ --> wordpress:80/blog/ #会访问wordpress下的blog
          url rewrite    #可以通过rewrite跳转到wordpress/下
            --annotation nginx.ingress.kubernetes.io/rewrite-target="/"
            
        基于主机名的虚拟主机 
        SSL 

 

2 Ingress的类型

类型一:Simple fanout

#主机一样,路径不同

  类型二:Name based virtual hosting

#每一个服务使用一个独立的主机名
#例:
service1.magedu.com
service2.magedu.com

类型三:TLS

#把其中一个主机名配置为https

 

3 Ingress 资源

部署Ingress-Nginx

#官网
https://github.com/kubernetes/ingress-nginx #注意表中Ingress-NGINX版本对k8s版本的适配
https://kubernetes.github.io/ingress-nginx/deploy/

#部署Ingress-Nginx
]#kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.0-beta.0/deploy/static/provider/cloud/deploy.yaml

#查看资源对象(会创建在ingress-nginx的名称空间中)
[root@master01 ~]#kubectl get all -n ingress-nginx
...#因为部署了metallb,这里ingress-nginx-controller服务自动分配了EXTERNAL-IP
service/ingress-nginx-controller             LoadBalancer   10.96.135.77   10.0.0.52     80:32563/TCP,443:30464/TCP   12m
[root@master01 ~]#kubectl get pods -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-sx2t8        0/1     Completed   0          3h
ingress-nginx-admission-patch-4djcx         0/1     Completed   0          3h
ingress-nginx-controller-7d56585cd5-6jdp5   1/1     Running     0          3h

#浏览器可以尝试访问ingress-nginx-controller服务,会报404 nginx,因为还没有主机
10.0.0.52
#部署Ingress-Nginx时,会自动创建叫nginx的ingressclass (部署controller都会创建一个对应ingressclass)
[root@master01 ~]#kubectl get ingressclass
NAME    CONTROLLER             PARAMETERS   AGE
nginx   k8s.io/ingress-nginx   <none>       76m

把服务开放到外部去访问

创建使用Ingress资源:
     kubectl create ingress NAME --rule=host/path=service:port[,tls[=secret]]  [options]
         --class #指定ingressclass是谁
         注意事项:
             (1) Ingress是名称空间级别的资源,它仅应该引用同一个名称空间下的Service;
             (2) 主机名不是集群上的资源对象,因而其作用范围为集群级别;

#实际操作示例(把demoapp服务通过ingress-nginx对外暴露):
#如果没有service,先创建一个service
]#kubectl create service clusterip demoapp --tcp=80:80
[root@master01 ~]#kubectl get svc
NAME                        TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/demoapp             ClusterIP      10.107.218.150   <none>        80/TCP         14s

#创建Ingress资源(主机:demoapp.magedu.com;路径:/表示起始路径/*起始与所有路径,加''防止*被shell解析)
#ingress要开发sevice通常在同一名称空间
#先测试输出看看效果
]#kubectl create ingress demoapp --rule='demoapp.magedu.com/*'=demoapp:80 --class=nginx --dry-run -o yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  creationTimestamp: null
  name: demoapp
spec:
  ingressClassName: nginx
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp
            port:
              number: 80
        path: /
        pathType: Prefix #/*就是Prefix;如果是/就是Exact,精确匹配/(不会代理/abc)
status:
  loadBalancer: {}
]#kubectl create ingress demoapp --rule='demoapp.magedu.com/*'=demoapp:80 --class=nginx
#也可以使用下面声明式对象配置
]#kubectl create ingress demoapp --rule='demoapp.magedu.com/*'=demoapp:80 --class=nginx --dry-run=client -o yaml > ingress-demoapp.yaml
]#kubectl apply -f ingress-demoapp.yaml

#查看ingress资源
[root@master01 ~]#kubectl get ingress
NAME      CLASS   HOSTS                ADDRESS   PORTS   AGE
demoapp   nginx   demoapp.magedu.com             80      10s
#查看详情(底下Reason为sync,Scheduled for sync表示ingress已经被Ingress-Nginx加载并生效了)
[root@master01 ~]#kubectl describe ingress demoapp
...
Rules:
  Host                Path  Backends
  ----                ----  --------
  demoapp.magedu.com  
                      /   demoapp:80 (10.244.1.145:80,10.244.2.125:80,10.244.3.91:80)
Annotations:          <none>
Events:
  Type    Reason  Age                    From                      Message
  ----    ------  ----                   ----                      -------
  Normal  Sync    4m10s (x2 over 4m51s)  nginx-ingress-controller  Scheduled for sync
  
#测试,主机host文件配置 ingress-nginx-controller的EXTERNAL-IP给对应主机名
10.0.0.52 demoapp.magedu.com
#浏览器访问即可返回,刷新会自动跳转到各个pod
demoapp.magedu.com
#进入nginx的pod中查看,nginx的conf中上游通过lua脚本实现上游怎么发现,使用什么balance代理(如删除ingress资源,nginx会自动把对应配置删除)
#ingress-nginx会读取ingress资源变动,并将其映射为自己配置文件上的配置,并让niginx随时动态按需重载


#示例(把wordpress暴露到外面)
#创建ingress
]#kubectl create ingress wordpress --rule='blog.magedu.com/*'=wordpress:80 --class=nginx -n blog
#查看ingress
]#kubectl describe ingress wordpress -n blog

#把blog.magedu.com配入宿主机host文件中,访问测试

Annotation(了解, 早期使用)

    Annotation:#可以给ingress-nginx配置更多参数
        注解信息;添加到资源对象上的kv类型的数据;
            键标识:[prefix/]key
        不适用于标签选择器来过滤资源对象;
            
        常用于为资源提供注释信息,该信息还可以被特定的控制器解读为应用的配置的信息
        #yaml中使用格式    
        metadata:
            labels: 
                ...
            annotations:
                ...
              
        命令:kubectl annotate     #使用方式和label相同
        
#ingress-nginx配置参数参考
https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/
#例:
#url重写路径
nginx.ingress.kubernetes.io/enable-rewrite-log    "true" or "false"

把ingress配置为ssl的类型

SSL Ingress: 
    准备secret
    创建Ingress,指明要加载secret中的证书和私钥
kubectl create ingress NAME --rule=host/path=service:port[,tls[=secret]]  [options]

#示例
#创建私钥
[root@master01 ~]#(umask 011;openssl genrsa -out demoapp.key 2048)
#基于demoapp.key创建自签证书(subj指定证书持有者信息)
[root@master01 ~]#openssl req -new -x509 -key ./demoapp.key -out ./demoapp.crt -days=3655 -subj="/CN=demoapp.magedu.com"

#创建成secret(类型tls,名称demoapp-ssl)
[root@master01 ~]#kubectl create secret tls demoapp-ssl --key=./demoapp.key --cert=./demoapp.crt
#查看
[root@master01 ~]#kubectl get secrets

#删除前面的ingress,重新建简单些
[root@master01 ~]#kubectl delete ingress demoapp
#创建ingress
]#kubectl create ingress demoapp --rule='demoapp.magedu.com/*'=demoapp:80,tls=demoapp-ssl --class=nginx

#查看是否完成同步(Scheduled for sync说明完成了同步)
[root@master01 ~]#kubectl describe ingress demoapp
...
  Normal  Sync    23s   nginx-ingress-controller  Scheduled for sync
  
#浏览器访问(点高级,继续访问即可)
https://demoapp.magedu.com/

简单扇出:基于单一虚拟主机使用不同的Path开放多服务(用的比较少)

#注意: 把www.magedu.com/demoapp/路径映射出去,demoapp也需要/demoapp/路径,没有可以用rewrite做url重写
简单扇出:基于单一虚拟主机使用不同的Path开放多服务  
    http://magedu.com/blog/ --> wordpress:80/blog/ #会访问wordpress下的blog
    url rewrite    #可以通过rewrite跳转到wordpress/下
        --annotation nginx.ingress.kubernetes.io/rewrite-target="/"

#创建ingress
]#kubectl create ingress www --rule='www.magedu.com/demoapp/*'=demoapp:80 --class=nginx --annotation nginx.ingress.kubernetes.io/rewrite-target="/"

#修改host文件,浏览器访问测试
http://www.magedu.com/demoapp/

 

4 基于Ingress Nginx 进行灰度发布

基于Ingress Nginx的灰度发布

Ingress-Nginx支持配置Ingress Annotations来实现不同场景下的灰度发布和测试,它能够满足金丝雀发
布、蓝绿部署与A/B测试等不同的业务场景

基于Ingress Nginx的Canary规则

https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/
#ingress-nginx配置参数canary,true:当前ingress规则发新版本,false或没设:接入流量发给旧版本(相当于发布开关)
nginx.ingress.kubernetes.io/canary    "true" or "false"
#如果上面的发布开关canary为true,流量怎么在新旧版本之间做调整,通过下面参数
nginx.ingress.kubernetes.io/canary-by-header    string
nginx.ingress.kubernetes.io/canary-by-header-value    string
nginx.ingress.kubernetes.io/canary-by-header-pattern    string
nginx.ingress.kubernetes.io/canary-by-cookie    string
nginx.ingress.kubernetes.io/canary-weight    number
nginx.ingress.kubernetes.io/canary-weight-total    number

Ingress Nginx Annotations支持的Canary规则
  ◼ nginx.ingress.kubernetes.io/canary-by-header:基于该Annotation中指定Request Header进行流量切分,适用于灰度发布以及A/B测试
    ◆在请求报文中,若存在该Header且其值为always时,请求将会被发送到Canary版本
    ◆若存在该Header且其值为never时,请求将不会被发送至Canary版本
    ◆对于任何其它值,将忽略该Annotation指定的Header,并通过优先级将请求与其他金丝雀规则进行优先级的比较
  ◼ nginx.ingress.kubernetes.io/canary-by-header-value:基于该Annotation中指定的Request Header的值进行流量切分,标头名称则由前一个Annotation(nginx.ingress.kubernetes.io/canary-by-header)进行指定
    ◆请求报文中存在指定的标头,且其值与该Annotation的值匹配时,它将被路由到Canary版本
    ◆对于任何其它值,将忽略该Annotation
  ◼ nginx.ingress.kubernetes.io/canary-by-header-pattern
    ◆同canary-by-header-value的功能类似,但该Annotation基于正则表达式匹配Request Header的值
    ◆若该Annotation与canary-by-header-value同时存在,则该Annotation会被忽略
    
Ingress Nginx Annotations支持的Canary规则(续)
  ◼ nginx.ingress.kubernetes.io/canary-weight:基于服务权重进行流量切分,适用于蓝绿部署,权重范围0 - 100按百分比将请求路由到Canary Ingress中指定的服务
    ◆权重为 0 意味着该金丝雀规则不会向Canary入口的服务发送任何请求
    ◆权重为100意味着所有请求都将被发送到 Canary 入
  ◼ nginx.ingress.kubernetes.io/canary-by-cookie:基于 cookie 的流量切分,适用于灰度发布与 A/B 测试
    ◆cookie的值设置为always时,它将被路由到Canary入口
    ◆cookie的值设置为 never时,请求不会被发送到Canary入口
    ◆对于任何其他值,将忽略 cookie 并将请求与其他金丝雀规则进行优先级的比较
    
规则的应用次序
  ◼ Canary规则会按特定的次序进行评估
  ◼ 次序:canary-by-header -> canary-by-cookie -> canary-weight #如果没匹配到就发给旧版本


工作负载型控制器的高级实现(了解):#支持高级发布功能(金丝雀,蓝绿发布)
    Argo Rollouts,可取代Deployment的全部功能
    OpenKruise Kruise Rollouts

实际操作示例(各种发布规则)

#把当前default名称空间下的资源都删了,免得干扰
]#kubectl delete deployments,service,statefulset --all
]#kubectl delete ingress --all

#创建demoapp的Deployment和service
[root@master01 ingress-canary-demo]#kubectl apply -f deploy-demoap-v1_0.yaml
#创建ingress
[root@master01 ingress-canary-demo]#vim 01-ingress-demoapp.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demoapp
  annotations: #改字段已经被废,能用,用ingressClassName代替
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v10
            port:
              number: 80
        path: /
        pathType: Prefix

[root@master01 ingress-canary-demo]#kubectl apply -f 01-ingress-demoapp.yaml
#浏览器输入,测试
demoapp.magedu.com

#创建新版本对应的Deployment和service
[root@master01 ingress-canary-demo]#kubectl apply -f deploy-demoap-v1_1.yaml

#ingress上加配置,迁一部分流量到新版本
[root@master01 ingress-canary-demo]#vim 02-canary-by-header.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/canary: "true" #启动canary功能
    nginx.ingress.kubernetes.io/canary-by-header: "X-Canary" #有该标头发给新版本
  name: demoapp-canary-by-header
spec:
  ingressClassName: nginx
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v11 #新版本服务
            port:
              number: 80
        path: /
        pathType: Prefix
[root@master01 ingress-canary-demo]#kubectl apply -f 02-canary-by-header.yaml
#查看,现在有2个ingress
[root@master01 ingress-canary-demo]#kubectl get ingress
NAME                       CLASS    HOSTS                ADDRESS     PORTS   AGE
demoapp                    <none>   demoapp.magedu.com   10.0.0.52   80      39m
demoapp-canary-by-header   nginx    demoapp.magedu.com   10.0.0.52   80      7m56s

#在另一台机器上配置host做测试
[root@node01 ~]#curl demoapp.magedu.com #请求老版本
iKubernetes demoapp v1.0 !! ClientIP: 10.244.2.138, ServerName: demoapp-v10-7895f997b5-spljs, ServerIP: 10.244.1.158!
#加入请求头X-Canary: always, 请求新版
[root@node01 ~]#curl -H "X-Canary: always" demoapp.magedu.com
iKubernetes demoapp v1.1 !! ClientIP: 10.244.2.138, ServerName: demoapp-v11-559fc44c47-27ncl, ServerIP: 10.244.1.159!
[root@node01 ~]#curl -H "X-Canary: a" demoapp.magedu.com #请求老版本(因为不是always)
iKubernetes demoapp v1.0 !! ClientIP: 10.244.2.138, ServerName: demoapp-v10-7895f997b5-spljs, ServerIP: 10.244.1.158!
#把02的发布规则删掉
[root@master01 ingress-canary-demo]#kubectl delete -f 02-canary-by-header.yaml

#在02基础上追加了自定义规则值
]#vim 03-canary-by-header-value.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "IsVIP" #存在这个标头,且值为false,就发给canary
    nginx.ingress.kubernetes.io/canary-by-header-value: "false"
  name: demoapp-canary-by-header-value
spec:
  ingressClassName: nginx
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v11
            port:
              number: 80
        path: /
        pathType: Prefix
[root@master01 ingress-canary-demo]#kubectl apply -f 03-canary-by-header-value.yaml
[root@master01 ingress-canary-demo]#kubectl get ingress
NAME                             CLASS    HOSTS                ADDRESS     PORTS   AGE
demoapp                          <none>   demoapp.magedu.com   10.0.0.52   80      44m
demoapp-canary-by-header-value   nginx    demoapp.magedu.com   10.0.0.52   80      35s
#测试
[root@node01 ~]#curl -H "IsVIP: false" demoapp.magedu.com
iKubernetes demoapp v1.1 !! ClientIP: 10.244.2.138, ServerName: demoapp-v11-559fc44c47-27ncl, ServerIP: 10.244.1.159!
[root@node01 ~]#curl demoapp.magedu.com
iKubernetes demoapp v1.0 !! ClientIP: 10.244.2.138, ServerName: demoapp-v10-7895f997b5-spljs, ServerIP: 10.244.1.158!
[root@node01 ~]#curl -H "IsVIP: always" demoapp.magedu.com
iKubernetes demoapp v1.0 !! ClientIP: 10.244.2.138, ServerName: demoapp-v10-7895f997b5-spljs, ServerIP: 10.244.1.158!
#把新的发布规则删掉,以免干扰
[root@master01 ingress-canary-demo]#kubectl delete -f 03-canary-by-header-value.yaml

[root@master01 ingress-canary-demo]#vim 04-canary-by-header-pattern.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "Username" #正则表达式匹配
    nginx.ingress.kubernetes.io/canary-by-header-pattern: "(vip|VIP)_.*"
  name: demoapp-canary-by-header-pattern
spec:
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v11
            port:
              number: 80
        path: /
        pathType: Prefix
[root@master01 ingress-canary-demo]#kubectl apply -f 04-canary-by-header-pattern.yaml
#测试
[root@node01 ~]#curl demoapp.magedu.com
iKubernetes demoapp v1.0 !! ClientIP: 10.244.2.138, ServerName: demoapp-v10-7895f997b5-spljs, ServerIP: 10.244.1.158!
[root@node01 ~]#curl -H "Username: vip_aaa" demoapp.magedu.com
iKubernetes demoapp v1.1 !! ClientIP: 10.244.2.138, ServerName: demoapp-v11-559fc44c47-27ncl, ServerIP: 10.244.1.159!
[root@master01 ingress-canary-demo]#kubectl delete -f 04-canary-by-header-pattern.yaml

#注意:上面3种方式,使用其中的任意一种

[root@master01 ingress-canary-demo]#vim 05-canary-by-weight.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "50" #新版本权重50%
  name: demoapp-canary-by-weight
spec:
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v11
            port:
              number: 80
        path: /
        pathType: Prefix
[root@master01 ingress-canary-demo]#kubectl apply -f 05-canary-by-weight.yaml
#测试,查看返回比例
[root@node01 ~]#while true; do curl demoapp.magedu.com; sleep .2; done
#删除,避免后续测试干扰
[root@master01 ingress-canary-demo]#kubectl delete -f 05-canary-by-weight.yaml

[root@master01 ingress-canary-demo]#vim 06-canary-by-cookie.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true" #有cookie,且vip_user=always就发给新版
    nginx.ingress.kubernetes.io/canary-by-cookie: "vip_user"
  name: demoapp-canary-by-cookie
spec:
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v11
            port:
              number: 80
        path: /
        pathType: Prefix
[root@master01 ingress-canary-demo]#kubectl apply -f 06-canary-by-cookie.yaml
#测试
[root@node01 ~]#curl demoapp.magedu.com
iKubernetes demoapp v1.0 !! ClientIP: 10.244.2.138, ServerName: demoapp-v10-7895f997b5-spljs, ServerIP: 10.244.1.158!
[root@node01 ~]#curl -b "vip_user=always" demoapp.magedu.com
iKubernetes demoapp v1.1 !! ClientIP: 10.244.2.138, ServerName: demoapp-v11-559fc44c47-27ncl, ServerIP: 10.244.1.159!
#删除,避免后续测试干扰
[root@master01 ingress-canary-demo]#kubectl delete -f 06-canary-by-cookie.yaml


#模拟蓝绿发布
#蓝绿发布,实际就是通过权重控制
[root@master01 ingress-canary-demo]#vim 05-canary-by-weight.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "0" #新版本权重为0
  name: demoapp-canary-by-weight
spec:
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v11
            port:
              number: 80
        path: /
        pathType: Prefix
[root@master01 ingress-canary-demo]#kubectl apply -f 05-canary-by-weight.yaml
#测试,查看返回比例,全是旧版本
[root@node01 ~]#while true; do curl demoapp.magedu.com; sleep .2; done

#等部署完新版本,新版本上线,手动测试能用,立即编辑05
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "100" #调整为100
  name: demoapp-canary-by-weight
spec:
  rules:
  - host: demoapp.magedu.com
    http:
      paths:
      - backend:
          service:
            name: demoapp-v11
            port:
              number: 80
        path: /
        pathType: Prefix
[root@master01 ingress-canary-demo]#kubectl apply -f 05-canary-by-weight.yaml
#测试,查看返回比例,全是新版本
[root@node01 ~]#while true; do curl demoapp.magedu.com; sleep .2; done

 

Helm程序包管理器

Helm: 
    包管理器:
        rpm/rpm, deb/dpkg, ...
        yum/dnf, apt/apt-get, ...

    helm, Chart:
        包格式:Chart, tgz打包格式 
        管理工具:Helm 

        Chart仓库:
            http/https 

            helm: 命令行客户端
                Chart仓库 
                API Server (kubeconfig文件) 

            仓库的位置:
                项目自身维护仓库
                公共仓库: oci://
                
        Chart中的yaml文件格式:
            模板文件 --> 向模板字串赋值 --> 完成模板渲染

            赋值方式:
                命令行选项:helm --set KEY=VALUE --set ...
                值文件:helm -f /PATH/TO/YAML_FILE 
                Chart通常会附带默认的值文件(values.yml)
                
    部署的实例:
        Release 
        
    helm程序组件:
        v2: 
            helm --> Tiller (部署运行在Kubernetes集群上) --> API Server 
        v3: 
            helm --> API Server 

Helm 基础

Helm是一款简化安装和管理Kubernetes应用程序的工具
  ◼ 可用于Kubernetes之上的应用程序管理的资源配置文件需要以特定的结构组织为Chart
    ◆Chart代表着可由Helm管理的有着特定格式的程序包
    ◆Chart中的资源配置文件通常以模板(go template)形式定义,在部署时,用户可通过向模板参数赋值实现定制化安装
的目的
    ◆各模板参数通常也有默认值,这些默认值定义在Chart包里一个名为values.yml的文件中
  ◼ 类似于kubectl,Helm也是Kubernetes API Server的命令行客户端工具
    ◆支持kubeconfig认证文件
    ◆需要事先从仓库或本地加载到要使用目标Chart,并基于Chart完成应用管理
    ◆Chart可缓存于Helm本地主机上
  ◼ 支持仓库管理和包管理的各类常用操作,例如Chart仓库的增、删、改、查,以及Chart包的制作、发布、搜索、下载等

 Helm社区的Artifact Hub

#官网
https://artifacthub.io/

Artifact Hub
  ◼ 由Helm社区维护的一个名为Artifact Hub的Web应用,旨在便于Chart的共享与分发
  ◼ 支持查询、安装和发布Kubernetes应用程序包

部署helm

#根据官网,可以下载自己所需要的版本
https://helm.sh/docs/intro/install/
#我这里选v3.16.3最新版本, Linux amd64版本 (go开发,静态编译,放在/usr/local/bin或/usr/bin下可直接使用)

#下载
[root@master01 ~]#curl -LO https://get.helm.sh/helm-v3.16.3-linux-amd64.tar.gz
[root@master01 ~]#tar xf helm-v3.16.3-linux-amd64.tar.gz
[root@master01 ~]#cd linux-amd64/
[root@master01 linux-amd64]#mv helm /usr/local/bin
[root@master01 linux-amd64]#cd
#可以使用helm了

#搜索chart,搜本地配置的仓库是repo, 搜Artifact Hub用hub
#搜本地仓库,这里因为没配本地仓库
]#helm search repo mysql
Error: no repositories configured
#搜Artifact Hub中包含mysql的
[root@master01 wordpress]#helm search hub mysql
URL            CHART VERSION    APP VERSION                DESCRIPTION
...

使用helm部署mysql示例

#Artifact Hub上搜mysql (bitnami是一个很大的开源组织) 可以参看默认参数
https://artifacthub.io/packages/helm/bitnami/mysql

#注意:helm install下dockerhub镜像,要网络代理,推荐使用环境变量的方法
]#export https_proxy="http://10.0.0.1:7890"
]#export http_proxy="http://10.0.0.1:7890"
]#export no_proxy="127.0.0.0/8,10.244.0.0/16,192.168.0.0/16,10.96.0.0/12,magedu.com,cluster.local"


#基于dockerhub上的oci仓库部署,创建mysql的release(下面没设的参数采用默认值)
helm install mysql  \
        --set auth.rootPassword='MageEdu' \
        --set global.storageClass=nfs-csi \ #可改为openebs-hostpath本地卷,提升性能
        --set architecture=replication \ #架构类型
        --set auth.database=wpdb \
        --set auth.username=wpuser \
        --set auth.password='magedu.com' \
        --set secondary.replicaCount=1 \ #从服务器几个实例
        --set auth.replicationPassword='replpass' \ #从服务器连主服务区使用的密码
        oci://registry-1.docker.io/bitnamicharts/mysql \
        -n wordpress --create-namespace #create-namespace如果名称空间不存在就创建
#自动到dockerhub上下载指定的chart,创建出一个release(部署主从复制的mysql)
#返回
NAME: mysql
LAST DEPLOYED: Tue Dec  3 04:36:34 2024
NAMESPACE: wordpress
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: mysql
CHART VERSION: 12.1.0
APP VERSION: 8.4.3 #mysql版本
#获取密码(用户root) 获取的其实就是设置的MageEdu
MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace wordpress mysql -o jsonpath="{.data.mysql-root-password}" | base64 -d)
  2. To connect to primary service (read/write):
      mysql -h mysql-primary.wordpress.svc.cluster.local -uroot -p"$MYSQL_ROOT_PASSWORD"
  3. To connect to secondary service (read-only):
      mysql -h mysql-secondary.wordpress.svc.cluster.local -uroot -p"$MYSQL_ROOT_PASSWORD"
      
#查看创建的东西
[root@master01 ~]#kubectl get all -n wordpress
NAME                    READY   STATUS    RESTARTS   AGE
pod/mysql-primary-0     1/1     Running   0          17m
pod/mysql-secondary-0   1/1     Running   0          17m

NAME                               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/mysql-primary              ClusterIP   10.103.149.119   <none>        3306/TCP   17m
service/mysql-primary-headless     ClusterIP   None             <none>        3306/TCP   17m
service/mysql-secondary            ClusterIP   10.108.47.42     <none>        3306/TCP   17m
service/mysql-secondary-headless   ClusterIP   None             <none>        3306/TCP   17m

NAME                               READY   AGE
statefulset.apps/mysql-primary     1/1     17m
statefulset.apps/mysql-secondary   1/1     17m

#查看刚刚部署的实例
[root@master01 wordpress]#helm list -n wordpress
NAME     NAMESPACE    REVISION    UPDATED                                    STATUS      CHART           APP VERSION
mysql    wordpress    1           2024-12-03 04:36:34.261136708 +0000 UTC    deployed    mysql-12.1.0    8.4.3 
#修改刚刚部署的实例参数(把要修改的参数换好直接提交)
helm upgrade mysql --set ...
#卸载
helm uninstall mysql
#查看状态(返回的就是刚刚部署返回的信息)
[root@master01 ~]#helm status mysql -n wordpress

使用helm部署wordpress示例

#artifacthub搜wordpress项目,可查看参数
https://artifacthub.io/packages/helm/bitnami/wordpress
#里面会内置mariadb解决依赖关系,但也是配置自己搭的mysql数据库,这里用上面的mysql主从架构

#基于dockerhub上的oci仓库部署
#使用已经部署完成的现有MySQL数据库,支持Ingress,且外部的MySQL是主从复制架构。注意修改如下命令中各参数值,以正确适配到自有环境。
helm install wordpress \
       --set mariadb.enabled=false \ #内置mariadb设为false
       --set externalDatabase.host=mysql-primary.wordpress.svc.cluster.local \
       --set externalDatabase.user=wpuser \
       --set externalDatabase.password='magedu.com' \
       --set externalDatabase.database=wpdb \
       --set externalDatabase.port=3306 \
       --set persistence.storageClass=nfs-csi \
       --set ingress.enabled=true \ #自动创建ingress
       --set ingress.ingressClassName=nginx \
       --set ingress.hostname=wordpress.magedu.com \
       --set ingress.pathType=Prefix \
       --set wordpressUsername=admin \ #管理员用户
       --set wordpressPassword='magedu.com' \
       oci://registry-1.docker.io/bitnamicharts/wordpress \
       -n wordpress --create-namespace
#返回
   echo "WordPress URL: http://wordpress.magedu.com/"
3. Login with the following credentials below to see your blog:
  echo Username: admin
  echo Password: $(kubectl get secret --namespace wordpress wordpress -o jsonpath="{.data.wordpress-password}" | base64 -d)

#查看release
[root@master01 wordpress]#helm list -n wordpress
NAME         NAMESPACE    REVISION    UPDATED                                    STATUS         CHART               APP VERSION
mysql        wordpress    1           2024-12-03 04:36:34.261136708 +0000 UTC    deployed       mysql-12.1.0        8.4.3      
wordpress    wordpress    1           2024-12-03 08:21:00.881921331 +0000 UTC    deployed       wordpress-24.0.8    6.7.1
#查看pvc
[root@master01 wordpress]#kubectl get pvc -n wordpress
NAME                     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
data-mysql-primary-0     Bound    pvc-294397e1-666d-4c94-9f8d-93f008f08d4f   8Gi        RWO            nfs-csi        <unset>                 3h49m
data-mysql-secondary-0   Bound    pvc-10cc3453-0fc9-4271-9c0b-7d3e77d6220b   8Gi        RWO            nfs-csi        <unset>                 3h49m
wordpress                Bound    pvc-2071ac90-0a6b-4dc5-aacb-e5d17438c097   10Gi       RWO            nfs-csi        <unset>                 4m43s
#查看ingress,外部IP地址10.0.0.52
[root@master01 wordpress]#kubectl get ingress -n wordpress
NAME        CLASS   HOSTS                  ADDRESS     PORTS   AGE
wordpress   nginx   wordpress.magedu.com   10.0.0.52   80      8m52s
#等待wordpress的pod启动完成
[root@master01 ~]#kubectl get pods -n wordpress

#在windows上host配置wordpress.magedu.com,测试
#登录 admin/magedu.com
http://wordpress.magedu.com/wp-login.php

helm部署harbor示例

#artifacthub上官方的用的最多
https://artifacthub.io/packages/helm/harbor/harbor

#需要先添加仓库,名称为harbor
helm repo add harbor https://helm.goharbor.io
#查看本地仓库repo
[root@master01 ingress-canary-demo]#helm repo list
NAME      URL                     
harbor    https://helm.goharbor.io
#本地仓库repo搜索harbor,左侧仓库名,右侧chart名
[root@master01 ingress-canary-demo]#helm search repo harbor
NAME             CHART VERSION    APP VERSION    DESCRIPTION                                       
harbor/harbor    1.16.0           2.12.0         An open source trusted cloud native registry th...

#查看chart值文件
[root@master01 ingress-canary-demo]#helm show values harbor/harbor

#准备部署harbor所用参数值文件
[root@master01 harbor]#vim harbor-values.yaml
expose:
  type: ingress
  tls: #使用内置tls
    enabled: true  
    certSource: auto #自动生成自签证书
  ingress:
    hosts:
      core: registry.magedu.com
    className: "nginx"
    annotations:
      ingress.kubernetes.io/ssl-redirect: "true"
      ingress.kubernetes.io/proxy-body-size: "0"
      nginx.ingress.kubernetes.io/ssl-redirect: "true"
      nginx.ingress.kubernetes.io/proxy-body-size: "0"

ipFamily:
  ipv4: #只支持ipv4
    enabled: true
  ipv6:
    enabled: false
#外部访问必须通过该地址(这里指定主机名,ip地址访问不进来的)
externalURL: https://registry.magedu.com

# 持久化存储配置部分
persistence:
  enabled: true 
  resourcePolicy: "keep" #删除实例,对应存储还是保留下来
  persistentVolumeClaim:        # 定义Harbor各个组件的PVC持久卷
    registry:          # registry组件(持久卷)
      storageClass: "nfs-csi"           # 前面创建的StorageClass,其它组件同样配置
      accessMode: ReadWriteMany          # 卷的访问模式,需要修改为ReadWriteMany
      size: 5Gi
    chartmuseum:     # chartmuseum组件(持久卷) 保存chart的仓库
      storageClass: "nfs-csi"
      accessMode: ReadWriteMany
      size: 5Gi
    jobservice:
      jobLog:
        storageClass: "nfs-csi"
        accessMode: ReadWriteOnce
        size: 1Gi
      #scanDataExports:
      #  storageClass: "nfs-csi"
      #  accessMode: ReadWriteOnce
      #  size: 1Gi
    database:        # PostgreSQl数据库组件
      storageClass: "nfs-csi"
      accessMode: ReadWriteMany
      size: 2Gi
    redis:    # Redis缓存组件
      storageClass: "nfs-csi"
      accessMode: ReadWriteMany
      size: 2Gi
    trivy:         # Trity漏洞扫描
      storageClass: "nfs-csi"
      accessMode: ReadWriteMany
      size: 5Gi

harborAdminPassword: "magedu.com"

#部署harbor (harbor仓库下/harbor的chart)
]#helm install harbor -f harbor-values.yaml harbor/harbor -n harbor --create-namespace
#查看harbor release
[root@master01 harbor]#helm list -n harbor
NAME      NAMESPACE    REVISION    UPDATED                                    STATUS      CHART            APP VERSION
harbor    harbor       1           2024-12-03 10:01:23.556792261 +0000 UTC    deployed    harbor-1.16.0    2.12.0     
[root@master01 harbor]#kubectl get ingress -n harbor
NAME             CLASS   HOSTS                 ADDRESS     PORTS     AGE
harbor-ingress   nginx   registry.magedu.com   10.0.0.52   80, 443   3m49s
#等待pod启动完成
[root@master01 harbor]#kubectl get pods -n harbor

#windows下hosts中添加
10.0.0.52 registry.magedu.com
#浏览器输入测试(关掉vpn就可以了,可能需要修改环境变量no_proxy)   admin/magedu.com
https://registry.magedu.com

#显示出当时部署时的自定义值文件内容
[root@master01 harbor]#helm get values harbor -n harbor
#显示所有渲染出的资源配置文件
[root@master01 harbor]#helm get manifest harbor -n harbor
##显示出当时部署时的自定义值文件内容,命令行参数也可以
[root@master01 harbor]#helm get values mysql -n wordpress
USER-SUPPLIED VALUES:
architecture: replication
auth:
  database: wpdb
  password: magedu.com
  replicationPassword: replpass
  rootPassword: MageEdu
  username: wpuser
global:
  storageClass: nfs-csi
secondary:
  replicaCount: 1

#显示创建完成后的提示信息,helm get notes也可以显示
[root@master01 harbor]#helm get notes mysql -n wordpress

获取并使用Helm

部署Helm
  ◼ 使用操作系统包管理器安装,支持Homebrew、Chocolatey、Scoop、GoFish和Snap等包管理器
  ◼ 直接下载适合目标平台的二进制Helm程序包,展开并放置于合适的位置即可使用
    ◆https://github.com/helm/helm/releases
常用的helm命令
  ◼ Repostory管理 #仓库里的元数据比较旧了,通过update更新元数据,可以下更新的数据(和apt update一样)
    ◆repo命令,支持repository的add、list、remove、update和index等子命令
  ◼ Chart管理
    ◆create、 package、pull、 push、dependency、search、show和verify等操作
  ◼ Release管理
    ◆install、upgrade、get、list、history、status、rollback和uninstall等操作

 

posted @ 2024-12-03 19:00  战斗小人  阅读(30)  评论(0编辑  收藏  举报