中间件容器化Helm&Operator

一.如何部署应用到K8S


当我们需要部署应用时后,考虑是否需要部署到K8S时一般需要考虑上图的几个因素。
1.我们部署应用的架构是怎么样的:比如你要部署redis集群到K8S,就要了解redis集群架构是怎么样的;redis需要怎么样的配置,配置文件怎么加载(环境变量or配置文件),一些云原生的配置文件可以通过加载环境变量,例如rabbitMQ;程序监控端口是什么(redis6379,rabbit5672,15672),启动命令(./redis-server 配置文件 ).
2.镜像谁来做:如果是公司自己的程序,那就自己做。如果是一个中间件,别人开发的,那么镜像在官方都是有的,不需要自己做,官方做的比自己做的好。
3.找合适的部署方式:是否有状态的(倾向无状态应用deployment,中间件很多需要存储挂载PVC),配置分离:一般都是需要把配置文件分离,一些中间件可以通过环境变量加载的,就直接填环境变量,否则配置需要分离出来做成configmap,然后挂载在容器中;
4.然后这个程序如何被使用:什么协议,内部使用还是外部使用,比如redsi使用TCP协议,例如rabbitMQ使用web客户端访问监控端使用http协议,如果是一个TCP协议的内部访问,使用svc名称就可以访问,外部访问的话一般用NODEPORT暴露出去。如果是http协议可以用ingress外部代理出去使用。

二.部署一个单实例到K8S

1、找到官方镜像:https://hub.docker.com/
2、确认需要的配置:环境变量或配置文件
3、选择部署方式:Deployment或其他的
4、配置访问:TCP或HTTP

1.部署rabbitMQ到K8S

首先在官网网站找到rabbitMQ的镜像,搜索选择合适的镜像下载同步到公司的镜像仓库。


确认配置文件:rabbitMQ是可以通过环境变量方式经行配置
然后确认部署方式:由于rabbitMQ是单实例,所以可以用deployment部署,消息队列一般要保存数据做持久化,所以也要挂载PVC(挂载目录/var/lib/rabbitmq)。
写deployment,pvc部署文件,可以官网找模板自己改:

[root@k8s-master01 ~]# vim rabbitMQ-deployment.yaml
apiVersion: v1
kind: Service
metadata:
  name: rabbitmq
  namespace: public-service
spec:
  ports:
  - name: web
    port: 5672
    protocol: TCP
    targetPort: 5672
  - name: http
    port: 15672
    protocol: TCP
    targetPort: 15672
  selector:
    app: rabbitmq
  sessionAffinity: None
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations: {}
  labels:
    app: rabbitmq
  name: rabbitmq
  namespace: public-service
spec:
  replicas: 1
  selector:
    matchLabels:
      app: rabbitmq
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: rabbitmq
    spec:
      affinity: {}
      containers:
      - env:
        - name: TZ
          value: Asia/Shanghai
        - name: LANG
          value: C.UTF-8
        - name: RABBITMQ_DEFAULT_USER   #通过环境变量配置默认管理员用户密码
          value: user
        - name: RABBITMQ_DEFAULT_PASS
          value: password
        image: rabbitmq:3.8.17-management
        imagePullPolicy: IfNotPresent
        lifecycle: {}
        livenessProbe:
          failureThreshold: 2
          initialDelaySeconds: 30
          periodSeconds: 10
          successThreshold: 1
          tcpSocket:
            port: 5672
          timeoutSeconds: 2
        name: rabbitmq
        ports:
        - containerPort: 5672
          name: web
          protocol: TCP
        readinessProbe:
          failureThreshold: 2
          initialDelaySeconds: 30
          periodSeconds: 10
          successThreshold: 1
          tcpSocket:
            port: 5672
          timeoutSeconds: 2
        resources:
          limits:
            cpu: 1000m
            memory: 1024Mi
          requests:
            cpu: 250m
            memory: 500Mi
      restartPolicy: Always

[root@k8s-master01 ~]# kubectl create ns public-service  #单独创建一个命名空间

[root@k8s-master01 ~]# kubectl create -f rabbitMQ-deployment.yaml
[root@k8s-master01 ~]# kubectl get pod -n public-service 
NAME                        READY   STATUS    RESTARTS   AGE
rabbitmq-77b5d5b747-6nl55   1/1     Running   3          2d

[root@k8s-master01 ~]# kubectl get svc -n public-service 
NAME       TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)                          AGE
rabbitmq   NodePort   10.108.113.166           5672:31142/TCP,15672:31317/TCP   2d1h

然后通过NodePort暴露一个端口访问,通过暴露的端口访问(用http)
http://192.168.0.236:32424/#/

三.传统架构和K8S管理中间件的区别

1.区别

传统架构:
如下图,比较复杂


k8s架构:
一句话总结功能就是可以很方便管理一些比较复杂的应用,比如MySQL集群、Redis集群等,可以一键式创建集群、扩容、备份等。常用的两种包管理工具是Operator和Helm。
helm:倾向于无状态应用的部署,比如公司的服务、某些不需要持久化数据的中间件、不需要实现额外功能的服务,比如备份、回滚等(比较容易)。
Operator:管理更为复杂的有状态服务,比如MySQL集群、Redis集群、Rook等。并且可以利用Operator实现扩容、备份、回滚等功能.(功能需要写代码实现,比较复杂)

2.中间件到底要不要部署在K8s

非生产环境:使用K8s管理比较推荐
非生产环境的中间件推荐所有都装在K8S中,一般测试环境不用考虑性能,稳定性,数据不需要持久化(mysql除外),也可以用动态存储rook。

生产环境:需要考虑性能、持久化、稳定性等问题。
mysql对磁盘IO要求比较高,一般可以考虑用云厂商的数据库。
生产环境需要考虑的比较多,一般结合项目需求,

四.Operator的使用

1.Operator部署redis集群

Operator常用的模板:https://github.com/operator-framework/awesome-operators
Redis Cluster Operator: https://github.com/ucloud/redis-cluster-operator


首先要先创建一些自定义的资源,K8S有很多kind,Operator可以管理这些创建的自定义kind

1、创建Operator-redis
git clone https://github.com/ucloud/redis-cluster-operator.git
cd  redis-cluster-operator/
kubectl create -f deploy/crds/redis.kun_distributedredisclusters_crd.yaml
kubectl create -f deploy/crds/redis.kun_redisclusterbackups_crd.yaml
kubectl create ns redis-cluster  #通过集群的方式创建,如果需要创建另一个集群,再创建一个redis-cluster2,同样执行下面4条命令即可
kubectl create -f deploy/service_account.yaml -n redis-cluster
kubectl create -f deploy/namespace/role.yaml -n redis-cluster
kubectl create -f deploy/namespace/role_binding.yaml -n redis-cluster
kubectl create -f deploy/namespace/operator.yaml -n redis-cluster

查看operator-redis:

[root@k8s-master01 redis-cluster-operator]# kubectl get pod -n redis-cluster 
NAME                                      READY   STATUS    RESTARTS   AGE
redis-cluster-operator-675ccbc697-gz6fw   1/1     Running   0          23s
2、创建redis集群

此文件可以定义集群的规模

[root@k8s-master01 redis-cluster-operator]# vim deploy/example/redis.kun_v1alpha1_distributedrediscluster_cr.yaml
apiVersion: redis.kun/v1alpha1
kind: DistributedRedisCluster
metadata:
  annotations:
    # if your operator run as cluster-scoped, add this annotations
    redis.kun/scope: cluster-scoped
  name: example-distributedrediscluster
spec:
  # Add fields here
  masterSize: 3   #master节点数
  clusterReplicas: 1   #每个主节点有几个从节点
  image: redis:5.0.4-alpine   #使用的镜像版本

创建:

[root@k8s-master01 redis-cluster-operator]# kubectl create -f deploy/example/redis.kun_v1alpha1_distributedrediscluster_cr.yaml  -n redis-cluster

【可选】提示:如果集群规模不大,资源少,可以自定义资源,把请求的资源降低
kubectl create -f  deploy/example/custom-resources.yaml  -n redis-cluster
3、扩容Redis集群

扩容Redis集群

grep "master" deploy/example/redis.kun_v1alpha1_distributedrediscluster_cr.yaml
		 masterSize: 4
kubectl replace -f deploy/example/redis.kun_v1alpha1_distributedrediscluster_cr.yaml -n redis-cluster
4、卸载集群
kubectl delete -f deploy/example/redis.kun_v1alpha1_distributedrediscluster_cr.yaml -n redis-cluster
kubectl delete -f deploy/cluster/operator.yaml -n redis-cluster
kubectl delete -f deploy/cluster/cluster_role_binding.yaml -n redis-cluster
kubectl delete -f deploy/cluster/cluster_role.yaml -n redis-cluster
kubectl delete -f deploy/service_account.yaml -n redis-cluster
kubectl delete -f deploy/crds/redis.kun_redisclusterbackups_crd.yaml -n redis-cluster
kubectl delete -f deploy/crds/redis.kun_distributedredisclusters_crd.yaml -n redis-cluster

五.Helm的使用

1.使用Helm创建Kafka、Zookeeper集群

首先安装heml,并添加仓库
a.下载安装包:https://github.com/helm/helm/releases
b.解压:tar -zxvf helm-v3.0.0-linux-amd64.tar.gz
c.复制到二进制目录:mv linux-amd64/helm /usr/local/bin/helm

[root@k8s-master01 bin]# which helm  #查看
/usr/local/bin/helm

d.添加bitnami和官方helm仓库:

[root@k8s-master01 ~]# helm repo add bitnami https://charts.bitnami.com/bitnami
[root@k8s-master01 ~]# helm repo add stable https://charts.helm.sh/stable

e.基础命令:

	下载一个包:helm pull
	创建一个包:helm create
	安装一个包:helm install
	查看:helm list
	查看安装参数:helm get values
	更新:helm upgrade
	删除:helm delete

f.安装方式一:先下载后安装
[root@k8s-master01 ~]# helm pull bitnami/zookeeper
[root@k8s-master01 ~]# tar xf zookeeper-7.5.1.tgz #解压
[root@k8s-master01 ~]# cd zookeeper && vim values.yaml #修改values.yaml相应配置:副本数、auth、持久化

image:镜像地址
replicaCount: 3  #副本数
persistence: 设置持久化,storageClass: sc-pvc名称

helm install -n public-service zookeeper . #安装
g.安装方式二:直接安装kafka
通过命名方式直接设置环境变量参数

[root@k8s-master01 zookeeper]# helm install kafka bitnami/kafka --set zookeeper.enabled=false --set replicaCount=3 --set externalZookeeper.servers=zookeeper --set persistence.enabled=false -n public-service

[root@k8s-master01 zookeeper]# kubectl get pod -n public-service  #2个集群都启动完成
NAME          READY   STATUS    RESTARTS   AGE
kafka-0       1/1     Running   0          4m11s
kafka-1       1/1     Running   0          4m11s
kafka-2       1/1     Running   0          4m11s
zookeeper-0   1/1     Running   0          23m
zookeeper-1   1/1     Running   0          23m
zookeeper-2   1/1     Running   0          23m

[root@k8s-master01 ~]# kubectl get svc -n public-service  #查看SVC
NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
kafka                ClusterIP   10.104.163.22            9092/TCP                     17m
kafka-headless       ClusterIP   None                     9092/TCP,9093/TCP            17m
zookeeper            ClusterIP   10.105.133.146           2181/TCP,2888/TCP,3888/TCP   37m
zookeeper-headless   ClusterIP   None                     2181/TCP,2888/TCP,3888/TCP   37m

2.Kafka验证

先起一个kafka客户端验证
kafka客户端:kubectl run kafka-client –restart=’Never’ –image docker.io/bitnami/kafka:2.8.0-debian-10-r30 –namespace public-service –command — sleep infinity

[root@k8s-master01 zookeeper]# kubectl get pod -n public-service | grep client
kafka-client 1/1 Running 0 39s

模拟生产者

[root@k8s-master01 zookeeper]# kubectl exec --tty -i kafka-client --namespace public-service -- bash  #进入kafka
I have no name!@kafka-client:/$ kafka-console-producer.sh \
>             --broker-list kafka-0.kafka-headless.public-service.svc.cluster.local:9092,kafka-1.kafka-headless.public-service.svc.cluster.local:9092,kafka-2.kafka-headless.public-service.svc.cluster.local:9092 \
>             --topic test
>1
>test 2
>xiaofei 1
>xiaofei2^H 
>wo123
模拟消费者
[root@k8s-master01 ~]#  kubectl exec --tty -i kafka-client --namespace public-service -- bash
I have no name!@kafka-client:/$         kafka-console-consumer.sh \
>             --bootstrap-server kafka.public-service.svc.cluster.local:9092 \
>             --topic test \
>             --from-beginning

1
test 2
xiaofei 1
xiaofei 
wo123

集群能正常消费,无异常

3.Kafka更新删除

更新和安装差不多,用heml upgrade更新

1.Kafka更新:

命令方式:

[root@k8s-master01 ~]# helm upgrade kafka bitnami/kafka --set zookeeper.enabled=false --set replicaCount=5 --set externalZookeeper.servers=zookeeper --set persistence.enabled=false -n public-service  #副本数改成5

yaml文件方式:

[root@k8s-master01 ~]# [root@k8s-master01 ~]# vim zookeeper/values.yaml
[root@k8s-master01 ~]# helm upgrade -n public-service zookeeper  . 
2.Kafka删除:
[root@k8s-master01 ~]# helm list -A   #查看helm数
NAME     	NAMESPACE     	REVISION	UPDATED                                	STATUS  	CHART          	APP VERSION
kafka    	public-service	1       	2021-12-16 18:21:58.629211542 +0800 CST	deployed	kafka-14.7.1   	2.8.1      
zookeeper	public-service	1       	2021-12-16 18:02:36.300204363 +0800 CST	deployed	zookeeper-7.5.1	3.7.0
[root@k8s-master01 ~]# helm delete -n publice-service fafka zookeeper  #删除即可

六.Helm的目录层级

创建一个Chart:helm create helm-test
├── charts # 依赖文件
├── Chart.yaml # 当前chart的基本信息
	apiVersion:Chart的apiVersion,目前默认都是v2
	name:Chart的名称
	type:图表的类型[可选]
	version:Chart自己的版本号
	appVersion:Chart内应用的版本号[可选]
	description:Chart描述信息[可选]
├── templates # 模板位置
│   ├── deployment.yaml
│   ├── _helpers.tpl # 自定义的模板或者函数
│   ├── ingress.yaml
│   ├── NOTES.txt #Chart安装完毕后的提醒信息
│   ├── serviceaccount.yaml
│   ├── service.yaml
│   └── tests # 测试文件
│       └── test-connection.yaml
└── values.yaml #配置全局变量或者一些参数

主要是values.yaml,定义全局变量,可以自定义参数,然后templates模板文件可以引用上面的变量,需要自己定义。

渲染配置文件,并不生成方式:会生成内置模板的yaml,包含sa,svc,deployment等自定义yaml。

[root@k8s-master01 helm-test]# helm install helm-test . --dry-run
NAME: helm-test
LAST DEPLOYED: Fri Dec 17 11:47:39 2021
NAMESPACE: default
STATUS: pending-install
REVISION: 1
HOOKS:
---
# Source: helm-test/templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
  name: "helm-test-test-connection"
  labels:
    helm.sh/chart: helm-test-0.1.0
    app.kubernetes.io/name: helm-test
    app.kubernetes.io/instance: helm-test
    app.kubernetes.io/version: "1.16.0"
    app.kubernetes.io/managed-by: Helm
  annotations:
    "helm.sh/hook": test
spec:
  containers:
    - name: wget
      image: busybox
      command: ['wget']
      args: ['helm-test:80']
  restartPolicy: Never
MANIFEST:
---
# Source: helm-test/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: helm-test
  labels:
    helm.sh/chart: helm-test-0.1.0
    app.kubernetes.io/name: helm-test
    app.kubernetes.io/instance: helm-test
    app.kubernetes.io/version: "1.16.0"
    app.kubernetes.io/managed-by: Helm
---
# Source: helm-test/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: helm-test
  labels:
    helm.sh/chart: helm-test-0.1.0
    app.kubernetes.io/name: helm-test
    app.kubernetes.io/instance: helm-test
    app.kubernetes.io/version: "1.16.0"
    app.kubernetes.io/managed-by: Helm
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app.kubernetes.io/name: helm-test
    app.kubernetes.io/instance: helm-test
---
# Source: helm-test/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: helm-test
  labels:
    helm.sh/chart: helm-test-0.1.0
    app.kubernetes.io/name: helm-test
    app.kubernetes.io/instance: helm-test
    app.kubernetes.io/version: "1.16.0"
    app.kubernetes.io/managed-by: Helm
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: helm-test
      app.kubernetes.io/instance: helm-test
  template:
    metadata:
      labels:
        app.kubernetes.io/name: helm-test
        app.kubernetes.io/instance: helm-test
    spec:
      serviceAccountName: helm-test
      securityContext:
        {}
      containers:
        - name: helm-test
          securityContext:
            {}
          image: "nginx:1.16.0"
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: http
          readinessProbe:
            httpGet:
              path: /
              port: http
          resources:
            {}

NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=helm-test,app.kubernetes.io/instance=helm-test" -o jsonpath="{.items[0].metadata.name}")
  export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT

七.Helm的内置变量

heml有些变量是没有在values中设置的,叫内置变量,如下常见内置变量:
Release.Name: 实例的名称,helm install指定的名字
Release.Namespace: 应用实例的命名空间
Release.IsUpgrade: 如果当前对实例的操作是更新或者回滚,这个变量的值就会被置为true
Release.IsInstall: 如果当前对实例的操作是安装,则这边变量被置为true
Release.Revision: 此次修订的版本号,从1开始,每次升级回滚都会增加1
Chart: Chart.yaml文件中的内容,可以使用Chart.Version表示应用版本,Chart.Name表示Chart的名称

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇