(一) 容器化中间件
1.如何部署应用到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外部代理出去使用。
2.部署一个单实例到K8S
1)找到官方镜像:https://hub.docker.com/
2)确认需要的配置:环境变量或配置文件
3)选择部署方式:Deployment或其他的
4)配置访问:TCP或HTTP
2.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/#/
3.传统架构和K8S管理中间件的区别
3.1.区别
传统架构: 如下图,比较复杂
k8s架构: 一句话总结功能就是可以很方便管理一些比较复杂的应用,比如MySQL集群、Redis集群等,可以一键式创建集群、扩容、备份等。常用的两种包管理工具是Operator和Helm。 helm:倾向于无状态应用的部署,比如公司的服务、某些不需要持久化数据的中间件、不需要实现额外功能的服务,比如备份、回滚等(比较容易)。 Operator:管理更为复杂的有状态服务,比如MySQL集群、Redis集群、Rook等。并且可以利用Operator实现扩容、备份、回滚等功能.(功能需要写代码实现,比较复杂)
3.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.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
1.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
【可选】提示:如果集群规模不大,资源少,可以自定义资源,把请求的资源降低</pre>
# kubectl create -f deploy/example/custom-resources.yaml -n redis-cluster</pre>
1.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
1.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更新
3.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</pre>
yaml文件方式:
[root@k8s-master01 ~]# [root@k8s-master01 ~]# vim zookeeper/values.yaml
[root@k8s-master01 ~]# helm upgrade -n public-service zookeeper .
3.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 #删除即可
4.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
5.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的名称
网友评论