zk,kafka,redis哨兵,mysql容器化

1. zookeeper,kafka容器化

1.1 zookeeper+kafka单机docker模式

docker pull bitnami/zookeeper:3.6.3-debian-11-r46
docker pull bitnami/kafka:3.1.1-debian-11-r36

docker run -itd --name zookeeper -p 2181:2181 -p 2888:2888 -p 3888:3888 -p 8080:8080  -e ALLOW_ANONYMOUS_LOGIN=yes  -e ALLOW_PLAINTEXT_LISTENER=yes bitnami/zookeeper:3.6.3-debian-11-r46 


docker run -itd --name kafka -p 9092:9092  -e ALLOW_ANONYMOUS_LOGIN=yes  -e ALLOW_PLAINTEXT_LISTENER=yes -e KAFKA_CFG_ZOOKEEPER_CONNECT=10.0.0.101:2181  bitnami/kafka:3.1.1-debian-11-r36 

#测试:

###创建topic  
[root@small-node1 ~]# docker exec -it kafka  bash
I have no name!@3772fdf40be2:/opt/bitnami/kafka/bin$ ./kafka-topics.sh  --create --bootstrap-server 10.0.0.101:9092 --replication-factor 1 --partitions 1 --topic test2
Created topic test2.

### 创建生产者
I have no name!@3772fdf40be2:/opt/bitnami/kafka/bin$ ./kafka-console-producer.sh --broker-list 10.0.0.101:9092 --topic test2
>halou world!
>

### 创建消息者
[root@small-node1 ~]# docker exec -it kafka bash
I have no name!@3772fdf40be2:/$ cd /opt/bitnami/kafka/bin/
I have no name!@3772fdf40be2:/opt/bitnami/kafka/bin$ ./kafka-console-consumer.sh --bootstrap-server 10.0.0.101:9092  --topic test2 --from-beginning
halou world!


#### 查询topic 
I have no name!@3772fdf40be2:/opt/bitnami/kafka/bin$ ./kafka-topics.sh  --bootstrap-server 10.0.0.101:9092  --list
__consumer_offsets
small-kafka
test1
test2
I have no name!@3772fdf40be2:/opt/bitnami/kafka/bin$ 

1.2 部署nfs动态存储类

#安装nfs服务
yum install -y nfs-utils
#创建对应服务数据目录
mkdir -p /data/k8s-nfs/{zookeeper,reids,mysql,kafka}

#更改nfs配置文件
[root@small-master ~/yml/zk-ka]# cat /etc/exports
/data/k8s-nfs/  *(rw,no_root_squash)

#重启nfs服务
[root@small-master ~/yml/zk-ka]# systemctl enable --now 
#检查nfs
[root@master ~/yml/sys]# showmount -e 10.0.0.151
Export list for 10.0.0.151:
/data/k8s-nfs/ *


git clone https://gitee.com/yinzhengjie/k8s-external-storage.git
mv k8s-external-storage yml/
cd  yml/nfs-storage/nfs-client/deploy/
#创建动态存储类
[root@small-master ~/yml/nfs-storage/nfs-client/deploy/]# cat class.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
  # archiveOnDelete: "false"
  archiveOnDelete: "true"
  
#创建授权角色
[root@small-master ~/yml/nfs-storage/nfs-client/deploy/]# cat rbac.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io
  
#部署nfs动态存储配置器
[root@small-master ~/yml/nfs-storage/nfs-client/deploy]# cat deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          image: small-node1:5000/small/saas/nfs-client:latest 
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: fuseim.pri/ifs
            - name: NFS_SERVER
            # 指定NFS服务器地址
              value: 10.0.0.100
            - name: NFS_PATH
            # 指定NFS的共享路径
              value: /data/k8s-nfs/
      volumes:
        - name: nfs-client-root
            # 配置NFS共享
          nfs:
            server: 10.0.0.100
            # path: /ifs/kubernetes
            path: /data/k8s-nfs/

kubectl apply -f class.yaml 
kubectl apply -f rbac.yaml 
kubectl apply -f deployment.yaml

#检查动态存储
[root@small-master ~/yml/nfs-storage/nfs-client/deploy]# kubectl get sc
NAME                  PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
managed-nfs-storage   fuseim.pri/ifs   Delete          Immediate           false                  57m

1.3 zookeeper+fafka单机K8S

k8s之StatefulSet详解

1)zookeeper

#nfs共享存储部署 略


#部署 zookeeper Service Headless 供sts使用
[root@small-master ~/yml/zk-ka]# cat zk-svc-headless.yml 
apiVersion: v1
kind: Service
metadata:
  name: zookeeper-headless
  labels:
    app: zookeeper
spec:
  type: ClusterIP
  clusterIP: None
  publishNotReadyAddresses: true
  ports:
  - name: client
    port: 2181
    targetPort: client
  - name: follower
    port: 2888
    targetPort: follower
  - name: election
    port: 3888
    targetPort: election
  selector:
    app: zookeeper

#部署zookeeper sts
[root@small-master ~/yml/zk-ka]# cat zk-sts.yml 
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: zookeeper
  labels:
    app: zookeeper
spec:
  serviceName: zookeeper-headless
  replicas: 1
  podManagementPolicy: Parallel
  updateStrategy:
    type: RollingUpdate
  selector:
    matchLabels:
      app: zookeeper
  template:
    metadata:
      name: zookeeper
      labels:
        app: zookeeper
    spec:      
      securityContext:
        fsGroup: 1001
      containers:
      - name: zookeeper
        image: docker.io/bitnami/zookeeper:3.4.14-debian-9-r25
        imagePullPolicy: IfNotPresent
        securityContext:
          runAsUser: 1001
        command:
         - bash
         - -ec
         - |
            # Execute entrypoint as usual after obtaining ZOO_SERVER_ID based on POD hostname
            HOSTNAME=`hostname -s`
            if [[ $HOSTNAME =~ (.*)-([0-9]+)$ ]]; then
              ORD=${BASH_REMATCH[2]}
              export ZOO_SERVER_ID=$((ORD+1))
            else
              echo "Failed to get index from hostname $HOST"
              exit 1
            fi
            . /opt/bitnami/base/functions
            . /opt/bitnami/base/helpers
            print_welcome_page
            . /init.sh
            nami_initialize zookeeper
            exec tini -- /run.sh            
        env:
        - name: ZOO_PORT_NUMBER
          value: "2181"
        - name: ZOO_TICK_TIME
          value: "2000"
        - name: ZOO_INIT_LIMIT
          value: "10"
        - name: ZOO_SYNC_LIMIT
          value: "5"
        - name: ZOO_MAX_CLIENT_CNXNS
          value: "60"
        - name: ZOO_SERVERS
          value: "
                  zookeeper-0.zookeeper-headless:2888:3888,
                 "
        - name: ZOO_ENABLE_AUTH
          value: "no"
        - name: ZOO_HEAP_SIZE
          value: "1024"
        - name: ZOO_LOG_LEVEL
          value: "ERROR"
        - name: ALLOW_ANONYMOUS_LOGIN
          value: "yes"
        ports:
        - name: client
          containerPort: 2181
        - name: follower
          containerPort: 2888
        - name: election
          containerPort: 3888
        livenessProbe:
          tcpSocket:
            port: client
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 6
        readinessProbe:
          tcpSocket:
            port: client
          initialDelaySeconds: 5
          periodSeconds: 10
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 6
        volumeMounts:
        - name: data
          mountPath: /bitnami/zookeeper
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi
      storageClassName: managed-nfs-storage


#部署 Service,用于外部访问 Zookeeper
[root@small-master ~/yml/zk-ka]# cat zk-svc.yml 
apiVersion: v1
kind: Service
metadata:
  name: zookeeper
  labels:
    app: zookeeper
spec:
  type: NodePort
  ports:
  - name: client
    port: 2181
    targetPort: 2181
    nodePort: 30107
  - name: follower
    port: 2888
    targetPort: follower
  - name: election
    port: 3888
    targetPort: election
  selector:
    app: zookeeper

2)kafka

#部署 headless,供sts使用
[root@small-master ~/yml/zk-ka]# cat kafka-svc-headless.yml 
apiVersion: v1
kind: Service
metadata:
  name: kafka-svc
  labels:
    app: kafka
spec:
  ports:
  - port: 9092
    name: server
  clusterIP: None
  selector:
    app: kafka

#部署kafka sts
#注意此处的zookeeper-0.zookeeper-headless.default.svc.cluster.local,如果zk指定了名称空间,这里的default就要替换成对应的名称名字
[root@small-master ~/yml/zk-ka]# cat kafka-sts.yml 
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: kafka-pdb
spec:
  selector:
    matchLabels:
      app: kafka
  minAvailable: 2
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: kafka
spec:
  selector:
    matchLabels:
      app: kafka
  serviceName: kafka-svc
  replicas: 1
  template:
    metadata:
      labels:
        app: kafka
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: "app"
                    operator: In
                    values:
                    - kafka
              topologyKey: "kubernetes.io/hostname"
        podAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
             - weight: 1
               podAffinityTerm:
                 labelSelector:
                    matchExpressions:
                      - key: "app"
                        operator: In
                        values:
                        - zk
                 topologyKey: "kubernetes.io/hostname"
      terminationGracePeriodSeconds: 300
      containers:
      - name: k8skafka
        imagePullPolicy: IfNotPresent
        image: small-node1:5000/small/saas/kafka:v1
        ports:
        - containerPort: 9092
          name: server
        command:
        - sh
        - -c
        - "exec kafka-server-start.sh /opt/kafka/config/server.properties --override broker.id=${HOSTNAME##*-} \
          --override listeners=PLAINTEXT://:9092 \
          --override zookeeper.connect=zookeeper-0.zookeeper-headless.default.svc.cluster.local \
          --override log.dir=/var/lib/kafka \
          --override auto.create.topics.enable=true \
          --override auto.leader.rebalance.enable=true \
          --override background.threads=10 \
          --override compression.type=producer \
          --override delete.topic.enable=false \
          --override leader.imbalance.check.interval.seconds=300 \
          --override leader.imbalance.per.broker.percentage=10 \
          --override log.flush.interval.messages=9223372036854775807 \
          --override log.flush.offset.checkpoint.interval.ms=60000 \
          --override log.flush.scheduler.interval.ms=9223372036854775807 \
          --override log.retention.bytes=-1 \
          --override log.retention.hours=168 \
          --override log.roll.hours=168 \
          --override log.roll.jitter.hours=0 \
          --override log.segment.bytes=1073741824 \
          --override log.segment.delete.delay.ms=60000 \
          --override message.max.bytes=1000012 \
          --override min.insync.replicas=1 \
          --override num.io.threads=8 \
          --override num.network.threads=3 \
          --override num.recovery.threads.per.data.dir=1 \
          --override num.replica.fetchers=1 \
          --override offset.metadata.max.bytes=4096 \
          --override offsets.commit.required.acks=-1 \
          --override offsets.commit.timeout.ms=5000 \
          --override offsets.load.buffer.size=5242880 \
          --override offsets.retention.check.interval.ms=600000 \
          --override offsets.retention.minutes=1440 \
          --override offsets.topic.compression.codec=0 \
          --override offsets.topic.num.partitions=50 \
          --override offsets.topic.replication.factor=3 \
          --override offsets.topic.segment.bytes=104857600 \
          --override queued.max.requests=500 \
          --override quota.consumer.default=9223372036854775807 \
          --override quota.producer.default=9223372036854775807 \
          --override replica.fetch.min.bytes=1 \
          --override replica.fetch.wait.max.ms=500 \
          --override replica.high.watermark.checkpoint.interval.ms=5000 \
          --override replica.lag.time.max.ms=10000 \
          --override replica.socket.receive.buffer.bytes=65536 \
          --override replica.socket.timeout.ms=30000 \
          --override request.timeout.ms=30000 \
          --override socket.receive.buffer.bytes=102400 \
          --override socket.request.max.bytes=104857600 \
          --override socket.send.buffer.bytes=102400 \
          --override unclean.leader.election.enable=true \
          --override zookeeper.session.timeout.ms=6000 \
          --override zookeeper.set.acl=false \
          --override broker.id.generation.enable=true \
          --override connections.max.idle.ms=600000 \
          --override controlled.shutdown.enable=true \
          --override controlled.shutdown.max.retries=3 \
          --override controlled.shutdown.retry.backoff.ms=5000 \
          --override controller.socket.timeout.ms=30000 \
          --override default.replication.factor=1 \
          --override fetch.purgatory.purge.interval.requests=1000 \
          --override group.max.session.timeout.ms=300000 \
          --override group.min.session.timeout.ms=6000 \
          --override inter.broker.protocol.version=0.10.2-IV0 \
          --override log.cleaner.backoff.ms=15000 \
          --override log.cleaner.dedupe.buffer.size=134217728 \
          --override log.cleaner.delete.retention.ms=86400000 \
          --override log.cleaner.enable=true \
          --override log.cleaner.io.buffer.load.factor=0.9 \
          --override log.cleaner.io.buffer.size=524288 \
          --override log.cleaner.io.max.bytes.per.second=1.7976931348623157E308 \
          --override log.cleaner.min.cleanable.ratio=0.5 \
          --override log.cleaner.min.compaction.lag.ms=0 \
          --override log.cleaner.threads=1 \
          --override log.cleanup.policy=delete \
          --override log.index.interval.bytes=4096 \
          --override log.index.size.max.bytes=10485760 \
          --override log.message.timestamp.difference.max.ms=9223372036854775807 \
          --override log.message.timestamp.type=CreateTime \
          --override log.preallocate=false \
          --override log.retention.check.interval.ms=300000 \
          --override max.connections.per.ip=2147483647 \
          --override num.partitions=1 \
          --override producer.purgatory.purge.interval.requests=1000 \
          --override replica.fetch.backoff.ms=1000 \
          --override replica.fetch.max.bytes=1048576 \
          --override replica.fetch.response.max.bytes=10485760 \
          --override reserved.broker.max.id=1000 "
        env:
        - name: KAFKA_HEAP_OPTS
          value : "-Xmx512M -Xms512M"
        - name: KAFKA_OPTS
          value: "-Dlogging.level=INFO"
        volumeMounts:
        - name: data
          mountPath: /var/lib/kafka
        readinessProbe:
          tcpSocket:
            port: 9092
          initialDelaySeconds: 30
          periodSeconds: 30
        livenessProbe:
          tcpSocket:
            port: 9092
          initialDelaySeconds: 60
      securityContext:
        runAsUser: 1000
        fsGroup: 1000
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi
      storageClassName: managed-nfs-storage

#部署 Service,用于外部访问 kafka
[root@small-master ~/yml/zk-ka]# cat kafka-svc.yml
apiVersion: v1
kind: Service
metadata:
  name: kafka-svc
  labels:
    app: kafka
spec:
  type: NodePort
  ports:
  - port: 9092
    name: server
    targetPort: 9092
    nodePort: 30108
  selector:
    app: kafka
    

3) 测试

#创建topic
[root@small-master ~]# kubectl exec -it kafka-0 bash
kafka@kafka-0:/$ kafka-topics.sh  --create --zookeeper zookeeper-0.zookeeper-headless.default.svc.cluster.local:2181  --replication-factor 1 --partitions 1 --topic aaa
Created topic "aaa".

#创建生产者
Ckafka@kafka-0:/$ kafka-console-producer.sh --topic aaa --broker-list localhost:9092
fsdafdsfs

#换个窗口模拟消费者
[root@small-master ~]# kubectl exec -it kafka-0 bash
kafka@kafka-0:/$ kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic aaa
fsdafdsfs

4)K8S集群外部连接kafka

如果K8S集群外部需要连接kafka,需要加 --override advertised.listeners=PLAINTEXT://172.18.0.125:39092 \ 这行配置,这里的ip为K8S集群宿主机的ip。否则连接失败,报错如下

1.4 zookeeper+kafka集群K8S

1)zookeeper

#去除主节点污点。保证pod的调度
[root@small-master ~/yml/zk-ka]# kubectl taint node small-master node-role.kubernetes.io/master-
node/small-master untainted

#对应yaml资源清单
[root@small-master ~/yml/zk-ka]# cat zookeeper-cm.yml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: zk-cm
data:
  jvm.heap: "1G"
  tick: "2000"
  init: "10"
  sync: "5"
  client.cnxns: "60"
  snap.retain: "3"
  purge.interval: "0"


[root@small-master ~/yml/zk-ka]# cat zookeeper-svc.yml 
apiVersion: v1
kind: Service
metadata:
  name: zk-svc
  labels:
    app: zk-svc
spec:
  ports:
  - port: 2888
    name: server
  - port: 3888
    name: leader-election
  clusterIP: None
  selector:
    app: zk
    
    
[root@small-master ~/yml/zk-ka]# cat zookeeper-sts.yml 
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  selector:
    matchLabels:
      app: zk
  minAvailable: 2
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: zk
spec:
  selector:
    matchLabels:
      app: zk
  serviceName: zk-svc
  replicas: 3
  template:
    metadata:
      labels:
        app: zk
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: "app"
                    operator: In
                    values:
                    - zk
              topologyKey: "kubernetes.io/hostname"
      containers:
      - name: k8szk
        imagePullPolicy: IfNotPresent
        image: small-node1:5000/small/saas/zookeeper:v1
        resources:
          limits:
            cpu: "1"
            memory: "2Gi"
          requests:
            cpu: "0.25"
            memory: "256Mi"
        ports:
        - containerPort: 2181
          name: client
        - containerPort: 2888
          name: server
        - containerPort: 3888
          name: leader-election
        env:
        - name : ZK_REPLICAS
          value: "3"
        - name : ZK_HEAP_SIZE
          valueFrom:
            configMapKeyRef:
                name: zk-cm
                key: jvm.heap
        - name : ZK_TICK_TIME
          valueFrom:
            configMapKeyRef:
                name: zk-cm
                key: tick
        - name : ZK_INIT_LIMIT
          valueFrom:
            configMapKeyRef:
                name: zk-cm
                key: tick
        - name : ZK_MAX_CLIENT_CNXNS
          valueFrom:
            configMapKeyRef:
                name: zk-cm
                key: client.cnxns
        - name: ZK_SNAP_RETAIN_COUNT
          valueFrom:
            configMapKeyRef:
                name: zk-cm
                key: snap.retain
        - name: ZK_PURGE_INTERVAL
          valueFrom:
            configMapKeyRef:
                name: zk-cm
                key: purge.interval
        - name: ZK_CLIENT_PORT
          value: "2181"
        - name: ZK_SERVER_PORT
          value: "2888"
        - name: ZK_ELECTION_PORT
          value: "3888"
        command:
        - sh
        - -c
        - zkGenConfig.sh && zkServer.sh start-foreground
        readinessProbe:
          exec:
            command:
            - "zkOk.sh"
          initialDelaySeconds: 10
          timeoutSeconds: 5
        livenessProbe:
          exec:
            command:
            - "zkOk.sh"
          initialDelaySeconds: 10
          timeoutSeconds: 5
        volumeMounts:
        - name: data
          mountPath: /var/lib/zookeeper
      securityContext:
        runAsUser: 1000
        fsGroup: 1000
# 卷申请模板,会为每个Pod去创建唯一的pvc并与之关联
  volumeClaimTemplates:
  - metadata:
  #这个data要和上面的volumenMounts里的name一致才会调用
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi
         # 声明自定义的动态存储类,即sc资源名称
      storageClassName: managed-nfs-storage

#部署
[root@small-master ~/yml/zk-ka]# kubectl apply -f zookeeper-cm.yml
[root@small-master ~/yml/zk-ka]# kubectl apply -f zookeeper-svc.yml
[root@small-master ~/yml/zk-ka]# kubectl apply -f zookeeper-sts.yml

#验证
[root@small-master ~/yml/zk-ka]# kubectl get po
NAME                                    READY   STATUS    RESTARTS      AGE
nfs-client-provisioner-8b8f8bd6-mpjb2   1/1     Running   1 (34m ago)   52m
zk-0                                    1/1     Running   0             75s
zk-1                                    1/1     Running   0             53s
zk-2                                    1/1     Running   0             31s
[root@small-master ~/yml/zk-ka]# for i in 0 1 2; do echo "myid zk-$i";kubectl exec zk-$i -- cat /var/lib/zookeeper/data/myid; done
myid zk-0
1
myid zk-1
2
myid zk-2
3
[root@small-master ~/yml/zk-ka]# for i in 0 1 2; do kubectl exec zk-$i -- hostname -f; done
zk-0.zk-svc.default.svc.cluster.local
zk-1.zk-svc.default.svc.cluster.local
zk-2.zk-svc.default.svc.cluster.local


#暴露外部服务
kubectl label pod zk-0 zkInst=0                                                                          
kubectl label pod zk-1 zkInst=1       
kubectl label pod zk-2 zkInst=2
                                                                      
kubectl expose po zk-0 --port=2181 --target-port=2181 --name=zk-0 --selector=zkInst=0 --type=NodePort
kubectl expose po zk-1 --port=2181 --target-port=2181 --name=zk-1 --selector=zkInst=1 --type=NodePort
kubectl expose po zk-2 --port=2181 --target-port=2181 --name=zk-2 --selector=zkInst=2 --type=NodePort

2)kafka

#svc-headless资源创建
[root@small-master ~/yml/zk-ka]# cat kafka-svc.yml 
apiVersion: v1
kind: Service
metadata:
  name: kafka-svc
  labels:
    app: kafka
spec:
  ports:
  - port: 9093
    name: server
  # 将clusterIP字段设置为None表示为一个无头服务.
  clusterIP: None
  selector:
    app: kafka


#sts资源创建
#注意此处的zookeeper-0.zookeeper-headless.default.svc.cluster.local,如果zk指定了名称空间,这里的default就要替换成对应的名称名字
[root@small-master ~/yml/zk-ka]# cat kafka-sts.yml 
---
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: kafka-pdb
spec:
  selector:
    matchLabels:
      app: kafka
  minAvailable: 2
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: kafka
spec:
  selector:
    matchLabels:
      app: kafka
  #声明无头服务  
  serviceName: kafka-svc
  replicas: 3
  template:
    metadata:
      labels:
        app: kafka
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: "app"
                    operator: In
                    values:
                    - kafka
              topologyKey: "kubernetes.io/hostname"
        podAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
             - weight: 1
               podAffinityTerm:
                 labelSelector:
                    matchExpressions:
                      - key: "app"
                        operator: In
                        values:
                        - zk
                 topologyKey: "kubernetes.io/hostname"
      terminationGracePeriodSeconds: 300
      containers:
      - name: k8skafka
        imagePullPolicy: IfNotPresent
        image: small-node1:5000/small/saas/kafka:v1
        resources:
          limits:
            cpu: "1"
            memory: "2Gi"
          requests:
            cpu: "0.25"
            memory: "256Mi"
        ports:
        - containerPort: 9093
          name: server
        command:
        - sh
        - -c
        - "exec kafka-server-start.sh /opt/kafka/config/server.properties --override broker.id=${HOSTNAME##*-} \
          --override listeners=PLAINTEXT://:9093 \
          --override zookeeper.connect=zk-0.zk-svc.default.svc.cluster.local:2181,zk-1.zk-svc.default.svc.cluster.local:2181,zk-2.zk-svc.default.svc.cluster.local:2181 \
          --override log.dir=/var/lib/kafka \
          --override auto.create.topics.enable=true \
          --override auto.leader.rebalance.enable=true \
          --override background.threads=10 \
          --override compression.type=producer \
          --override delete.topic.enable=false \
          --override leader.imbalance.check.interval.seconds=300 \
          --override leader.imbalance.per.broker.percentage=10 \
          --override log.flush.interval.messages=9223372036854775807 \
          --override log.flush.offset.checkpoint.interval.ms=60000 \
          --override log.flush.scheduler.interval.ms=9223372036854775807 \
          --override log.retention.bytes=-1 \
          --override log.retention.hours=168 \
          --override log.roll.hours=168 \
          --override log.roll.jitter.hours=0 \
          --override log.segment.bytes=1073741824 \
          --override log.segment.delete.delay.ms=60000 \
          --override message.max.bytes=1000012 \
          --override min.insync.replicas=1 \
          --override num.io.threads=8 \
          --override num.network.threads=3 \
          --override num.recovery.threads.per.data.dir=1 \
          --override num.replica.fetchers=1 \
          --override offset.metadata.max.bytes=4096 \
          --override offsets.commit.required.acks=-1 \
          --override offsets.commit.timeout.ms=5000 \
          --override offsets.load.buffer.size=5242880 \
          --override offsets.retention.check.interval.ms=600000 \
          --override offsets.retention.minutes=1440 \
          --override offsets.topic.compression.codec=0 \
          --override offsets.topic.num.partitions=50 \
          --override offsets.topic.replication.factor=3 \
          --override offsets.topic.segment.bytes=104857600 \
          --override queued.max.requests=500 \
          --override quota.consumer.default=9223372036854775807 \
          --override quota.producer.default=9223372036854775807 \
          --override replica.fetch.min.bytes=1 \
          --override replica.fetch.wait.max.ms=500 \
          --override replica.high.watermark.checkpoint.interval.ms=5000 \
          --override replica.lag.time.max.ms=10000 \
          --override replica.socket.receive.buffer.bytes=65536 \
          --override replica.socket.timeout.ms=30000 \
          --override request.timeout.ms=30000 \
          --override socket.receive.buffer.bytes=102400 \
          --override socket.request.max.bytes=104857600 \
          --override socket.send.buffer.bytes=102400 \
          --override unclean.leader.election.enable=true \
          --override zookeeper.session.timeout.ms=6000 \
          --override zookeeper.set.acl=false \
          --override broker.id.generation.enable=true \
          --override connections.max.idle.ms=600000 \
          --override controlled.shutdown.enable=true \
          --override controlled.shutdown.max.retries=3 \
          --override controlled.shutdown.retry.backoff.ms=5000 \
          --override controller.socket.timeout.ms=30000 \
          --override default.replication.factor=1 \
          --override fetch.purgatory.purge.interval.requests=1000 \
          --override group.max.session.timeout.ms=300000 \
          --override group.min.session.timeout.ms=6000 \
          --override inter.broker.protocol.version=0.10.2-IV0 \
          --override log.cleaner.backoff.ms=15000 \
          --override log.cleaner.dedupe.buffer.size=134217728 \
          --override log.cleaner.delete.retention.ms=86400000 \
          --override log.cleaner.enable=true \
          --override log.cleaner.io.buffer.load.factor=0.9 \
          --override log.cleaner.io.buffer.size=524288 \
          --override log.cleaner.io.max.bytes.per.second=1.7976931348623157E308 \
          --override log.cleaner.min.cleanable.ratio=0.5 \
          --override log.cleaner.min.compaction.lag.ms=0 \
          --override log.cleaner.threads=1 \
          --override log.cleanup.policy=delete \
          --override log.index.interval.bytes=4096 \
          --override log.index.size.max.bytes=10485760 \
          --override log.message.timestamp.difference.max.ms=9223372036854775807 \
          --override log.message.timestamp.type=CreateTime \
          --override log.preallocate=false \
          --override log.retention.check.interval.ms=300000 \
          --override max.connections.per.ip=2147483647 \
          --override num.partitions=1 \
          --override producer.purgatory.purge.interval.requests=1000 \
          --override replica.fetch.backoff.ms=1000 \
          --override replica.fetch.max.bytes=1048576 \
          --override replica.fetch.response.max.bytes=10485760 \
          --override reserved.broker.max.id=1000 "
        env:
        - name: KAFKA_HEAP_OPTS
          value : "-Xmx512M -Xms512M"
        - name: KAFKA_OPTS
          value: "-Dlogging.level=INFO"
        volumeMounts:
        - name: data
          mountPath: /var/lib/kafka
        readinessProbe:
          tcpSocket:
            port: 9093
          initialDelaySeconds: 30
          periodSeconds: 30
        livenessProbe:
          tcpSocket:
            port: 9093
          initialDelaySeconds: 60
          periodSeconds: 3
      securityContext:
        runAsUser: 1000
        fsGroup: 1000
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi
      storageClassName: managed-nfs-storage

[root@small-master ~/yml/zk-ka]# kubectl apply -f kafka-svc.yml
[root@small-master ~/yml/zk-ka]# kubectl apply -f kafka-sts.yml

#检查
[root@small-master ~/yml/zk-ka]# kubectl get po
NAME                                      READY   STATUS    RESTARTS   AGE
kafka-0                                   1/1     Running   1          48m
kafka-1                                   1/1     Running   0          48m
kafka-2                                   1/1     Running   0          47m
nfs-client-provisioner-85fc7b9595-shrl4   1/1     Running   1          3h56m
zk-0                                      1/1     Running   0          3h51m
zk-1                                      1/1     Running   0          3h50m
zk-2                                      1/1     Running   0          3h51m
[root@small-master ~/yml/zk-ka]# ll /data/k8s-nfs/
total 0
drwxrwxrwx 2 root root  6 Oct 13 18:34 archived-default-data-kafka-0-pvc-e11ab794-69be-46c7-98d7-0648599199e1
drwxrwxrwx 2 root root  6 Oct 13 18:36 default-data-kafka-0-pvc-90dacc70-3a01-4225-b17c-c94ebdbf72a0
drwxrwxrwx 2 root root  6 Oct 13 18:36 default-data-kafka-1-pvc-caf25d03-d143-4a83-a453-869413983dc2
drwxrwxrwx 2 root root  6 Oct 13 18:36 default-data-kafka-2-pvc-fde88742-8c3c-4908-ae26-634b8afa038a
drwxrwxrwx 4 root root 29 Oct 13 18:29 default-data-zk-0-pvc-8d49b10a-e772-4949-8402-b48288be1dc5
drwxrwxrwx 4 root root 29 Oct 13 18:30 default-data-zk-1-pvc-cd5f6119-5fab-4750-9554-f33a1a5f58a0
drwxrwxrwx 4 root root 29 Oct 13 18:31 default-data-zk-2-pvc-b866fe09-6650-4b12-a4bc-707becab1798

#验证:

[root@small-master ~]# kubectl exec -it kafka-0 bash
#创建topic
kafka@kafka-0:/opt/kafka/config$ kafka-topics.sh --create --topic ans  --zookeeper zk-0.zk-svc.default.svc.cluster.local:2181,zk-1.zk-svc.default.svc.cluster.local:2181,zk-2.zk-svc.default.svc.cluster.local:2181 --partitions 3 --replication-factor 2                        
Created topic "ans".

#创建生产者
kafka@kafka-0:/opt/kafka/config$ kafka-console-producer.sh --topic ans --broker-list localhost:9093  
fsdfsd

#创建消费者
[root@small-master ~]# kubectl exec -it kafka-1 bash
kafka@kafka-1:/opt/kafka/bin$ kafka-console-consumer.sh --bootstrap-server localhost:9093 --topic ans
fsdfsd


#检查zookeeper状态
[root@small-master ~/yml/zk-ka]# kubectl exec -it zk-0 bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
zookeeper@zk-0:/$ zkCli.sh  
Connecting to localhost:2181
2022-10-14 07:54:30,109 [myid:] - INFO  [main:Environment@100] - Client environment:zookeeper.version=3.4.10-39d3a4f269333c922ed3db283be479f9deacaa0f, built on 03/23/2017 10:13 GMT
2022-10-14 07:54:30,112 [myid:] - INFO  [main:Environment@100] - Client environment:host.name=zk-0.zk-svc.default.svc.cluster.local
2022-10-14 07:54:30,112 [myid:] - INFO  [main:Environment@100] - Client environment:java.version=1.8.0_131
2022-10-14 07:54:30,114 [myid:] - INFO  [main:Environment@100] - Client environment:java.vendor=Oracle Corporation
2022-10-14 07:54:30,114 [myid:] - INFO  [main:Environment@100] - Client environment:java.home=/usr/lib/jvm/java-8-openjdk-amd64/jre
2022-10-14 07:54:30,114 [myid:] - INFO  [main:Environment@100] - Client environment:java.class.path=/usr/bin/../build/classes:/usr/bin/../build/lib/*.jar:/usr/bin/../share/zookeeper/zookeeper-3.4.10.jar:/usr/bin/../share/zookeeper/slf4j-log4j12-1.6.1.jar:/usr/bin/../share/zookeeper/slf4j-api-1.6.1.jar:/usr/bin/../share/zookeeper/netty-3.10.5.Final.jar:/usr/bin/../share/zookeeper/log4j-1.2.16.jar:/usr/bin/../share/zookeeper/jline-0.9.94.jar:/usr/bin/../src/java/lib/*.jar:/usr/bin/../etc/zookeeper:
2022-10-14 07:54:30,114 [myid:] - INFO  [main:Environment@100] - Client environment:java.library.path=/usr/java/packages/lib/amd64:/usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib
2022-10-14 07:54:30,114 [myid:] - INFO  [main:Environment@100] - Client environment:java.io.tmpdir=/tmp
2022-10-14 07:54:30,114 [myid:] - INFO  [main:Environment@100] - Client environment:java.compiler=<NA>
2022-10-14 07:54:30,114 [myid:] - INFO  [main:Environment@100] - Client environment:os.name=Linux
2022-10-14 07:54:30,114 [myid:] - INFO  [main:Environment@100] - Client environment:os.arch=amd64
2022-10-14 07:54:30,114 [myid:] - INFO  [main:Environment@100] - Client environment:os.version=3.10.0-1160.el7.x86_64
2022-10-14 07:54:30,115 [myid:] - INFO  [main:Environment@100] - Client environment:user.name=zookeeper
2022-10-14 07:54:30,115 [myid:] - INFO  [main:Environment@100] - Client environment:user.home=/home/zookeeper
2022-10-14 07:54:30,115 [myid:] - INFO  [main:Environment@100] - Client environment:user.dir=/
2022-10-14 07:54:30,116 [myid:] - INFO  [main:ZooKeeper@438] - Initiating client connection, connectString=localhost:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@42110406
Welcome to ZooKeeper!
2022-10-14 07:54:30,161 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1032] - Opening socket connection to server localhost/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
JLine support is enabled
2022-10-14 07:54:30,367 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@876] - Socket connection established to localhost/127.0.0.1:2181, initiating session
2022-10-14 07:54:30,494 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1299] - Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x183d569ae680000, negotiated timeout = 30000

WATCHER::

#检查brokers
WatchedEvent state:SyncConnected type:None path:null
[zk: localhost:2181(CONNECTED) 0] ls /
[cluster, controller, controller_epoch, brokers, zookeeper, admin, isr_change_notification, consumers, config]
[zk: localhost:2181(CONNECTED) 1] ls /brokers
[ids, topics, seqid]
[zk: localhost:2181(CONNECTED) 4] ls /brokers/ids
[0, 1, 2]
#表示成功链接

2. redis哨兵,mysql容器化

2.1 redis单机模式

[root@small-master ~/yml/redis]# cat redis-alone.yaml 
apiVersion: v1
kind: Service
metadata:
  name: redis-svc
  labels:
    app: redis
spec:
  ports:
  - port: 6379 
    name: server
  clusterIP: None
  selector:
    app: redis

---

apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-conf
data:
  redis.conf: |
        bind 0.0.0.0
        port 6379
        requirepass Shuli@123
        pidfile .pid
        appendonly yes
        cluster-config-file nodes-6379.conf
        pidfile /data/middleware-data/redis/log/redis-6379.pid
        cluster-config-file /data/middleware-data/redis/conf/redis.conf
        dir /data/middleware-data/redis/data/
        logfile "/data/middleware-data/redis/log/redis-6379.log"
        cluster-node-timeout 5000
        protected-mode no

---

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
spec:
  serviceName: redis-headless
  replicas: 1
  serviceName: redis
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      initContainers:
      - name: init-redis
        image: busybox
        command: ['sh', '-c', 'mkdir -p /data/middleware-data/redis/log/;mkdir -p /data/middleware-data/redis/conf/;mkdir -p /data/middleware-data/redis/data/']
        volumeMounts:
        - name: data
          mountPath: /data/middleware-data/redis/
      containers:
      - name: redis
        image: harbor.data4truth.com:8443/paas/redis:5.0.5-alpine
        imagePullPolicy: IfNotPresent
        command:
        - sh
        - -c
        - "exec redis-server /data/middleware-data/redis/conf/redis.conf"
        ports:
        - containerPort: 6379
          name: redis
          protocol: TCP
        volumeMounts:
        - name: redis-config
          mountPath: /data/middleware-data/redis/conf/
        - name: data
          mountPath: /data/middleware-data/redis/
      volumes:
      - name: redis-config
        configMap:
          name: redis-conf
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi
      storageClassName: managed-nfs-storage

---

kind: Service
apiVersion: v1
metadata:
  labels:
    name: redis
  name: redis
spec:
  type: NodePort
  ports:
  - name: redis
    port: 6379
    targetPort: 6379
    nodePort: 31379
  selector:
    name: redis          


#验证:
[root@small-master ~/yml/redis]# kubectl get po
NAME                                      READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-85fc7b9595-h85pv   1/1     Running   0          61m
redis-0                                   1/1     Running   0          38s
[root@small-master ~/yml/redis]# kubectl exec -it redis-0 sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/data # redis-cli 
127.0.0.1:6379> auth Shuli@123
OK
127.0.0.1:6379> info Replication
# Replication
role:master
connected_slaves:0
master_replid:8571592c4a5fb224947f9e60a5846e489ac16030
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

2.2 redis哨兵模式

#dockerfile
[root@small-master ~/yml/redis/dockerfile]# cat Dockerfile 
FROM redis:6.0
MAINTAINER Ansheng

COPY *.conf /opt/conf/
COPY run.sh /opt/run.sh
RUN apt update -y;apt-get install vim net-tools -y;apt-get clean && \
    chmod +x /opt/run.sh

CMD /opt/run.sh

#redis配置文件
[root@small-master ~/yml/redis/dockerfile]# cat redis.conf 
#绑定到哪台机器,0.0.0.0表示允许所有主机访问
bind 0.0.0.0
#redis3.2版本之后加入的特性,yes开启后,如果没有配置bind则默认只允许127.0.0.1访问
protected-mode no
#对外暴露的访问端口
port 6379
#登录密码
requirepass shuli@123
#主从同步认证密码
masterauth shuli@123
#三次握手的时候server端接收到客户端 ack确认号之后的队列值
tcp-backlog 511
#服务端与客户端连接超时时间,0表示永不超时
timeout 30
#连接redis的时候的密码 hello
#requirepass hello
#tcp 保持会话时间是300s
tcp-keepalive 300
#redis是否以守护进程运行,如果是,会生成pid
daemonize yes
supervised no
#pid文件路径
pidfile /var/run/redis_6379.pid
#日志级别
loglevel notice
logfile /var/log/redis.log
#默认redis有几个db库
databases 16
#每间隔900秒,如果一个键值发生变化就触发快照机制
save 900 1
save 300 10
save 60 10000
#快照出错时,是否禁止redis写入
stop-writes-on-bgsave-error yes
#持久化到rdb文件时,是否压缩文件
rdbcompression yes
#持久化到rdb文件是,是否RC64开启验证
rdbchecksum yes
#持久化输出的时候,rdb文件命名
dbfilename dump.rdb
#持久化文件路径
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
#是否开启aof备份
appendonly yes
#aof备份文件名称
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
#客户端最大连接数
maxclients 20000
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
slave-lazy-flush yes


#sentinel配置文件
[root@small-master ~/yml/redis/dockerfile]# cat sentinel.conf 
# 哨兵sentinel实例运行的端口 默认26379
port 26379
# 哨兵sentinel的工作目录
dir "/tmp"
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster redis-0.redis 6379 2
sentinel auth-pass mymaster shuli@123
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 15000
# 设定5秒内没有响应,说明服务器挂了,需要将配置放在sentinel monitor master 127.0.0.1 6379 下面
sentinel parallel-syncs mymaster 2
# 设定15秒内master没有活起来,就重新选举主
sentinel config-epoch mymaster 3
#.表示如果master重新选出来后,其它slave节点能同时并行从新master同步缓存的台数有多少个,显然该值越大,所有slave节点完成同步切换的整体速度越快,但如果此时正好有人在访问这些slave,可能造成读取失败,影响面会更广。最保定的设置为1,只同一时间,只能有一台干这件事,这样其它slave还能继续服务,但是所有slave全部完成缓存更新同步的进程将变慢。
sentinel leader-epoch mymaster 3


#启动脚本
[root@small-master ~/yml/redis/dockerfile]# cat run.sh 
#!/bin/bash

pod_seq=$(echo $POD_NAME | awk -F"-" '{print $2}')
if [[ ${pod_seq} -ne 0 ]];then    #为从机
    sed -i '/^slaveof /d' /opt/conf/redis.conf
    echo "slaveof redis-0.redis 6379" >> /opt/conf/redis.conf	#redis-0.redis代表第一个redis的访问地址
fi
/usr/local/bin/redis-server /opt/conf/redis.conf
sleep 15    #如果redis-0没起来,它里面的哨兵也起不来,等待一段时间再启动哨兵
/usr/local/bin/redis-sentinel /opt/conf/sentinel.conf &
tail -f /var/log/redis.log


[root@small-master ~/yml/redis/dockerfile]# docker build --pull -t harbor.ans.cn/saas/redis_sentinel:6.0 .
[root@small-master ~/yml/redis/dockerfile]# docker push harbor.ans.cn/saas/redis_sentinel:6.0

#K8S redis yaml文件
[root@small-master ~/yml/redis]# cat redis-sentinel.yml 
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
spec:
  serviceName: redis
  selector:
    matchLabels:
      app: redis
  replicas: 3
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi
      storageClassName: managed-nfs-storage
  template:
    metadata:
      labels:
        app: redis
    spec:
      restartPolicy: Always
      containers:
        - name: redis
          image: harbor.ans.cn/saas/redis_sentinel:6.0
          imagePullPolicy: Always
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
          livenessProbe:
            tcpSocket:
              port: 6379
            initialDelaySeconds: 3
            periodSeconds: 5
          readinessProbe:
            tcpSocket:
              port: 6379
            initialDelaySeconds: 3
            periodSeconds: 5
          ports:
          - containerPort: 6379
          resources:
            limits:
              cpu: "1"
              memory: "2Gi"
            requests:
              cpu: "0.25"
              memory: "256Mi"
          volumeMounts:
          - name: data
            mountPath: /data
---

apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  type: NodePort
  ports:
    - name: redis
      port: 6379
      targetPort: 6379
      nodePort: 32222
  selector:
    app: redis

    
[root@small-master ~/yml/redis]# kubectl apply -f redis-sentinel.yml 
statefulset.apps/redis created
service/redis created
[root@small-master ~/yml/redis]# kubectl get po
NAME                                      READY   STATUS    RESTARTS   AGE
redis-0                                   1/1     Running   0          5m13s
redis-1                                   1/1     Running   0          5m6s
redis-2                                   1/1     Running   0          4m59s
[root@small-master ~/yml/redis]# cd /data/k8s-nfs/
[root@small-master /data/k8s-nfs]# ll
total 0
drwxrwxrwx 2 root root 44 Oct 18 15:09 default-data-redis-0-pvc-875ac01e-d5d8-427f-8cd5-ba590e714902
drwxrwxrwx 2 root root 44 Oct 18 15:08 default-data-redis-1-pvc-7268bf13-4619-48c7-987f-fe2ccc4d218d
drwxrwxrwx 2 root root 44 Oct 18 15:09 default-data-redis-2-pvc-41dc4e4c-65fe-42cb-b41e-9117a0659eba
[root@small-master /data/k8s-nfs]# tree
.
├── default-data-redis-0-pvc-875ac01e-d5d8-427f-8cd5-ba590e714902
│   ├── appendonly.aof
│   └── dump.rdb
├── default-data-redis-1-pvc-7268bf13-4619-48c7-987f-fe2ccc4d218d
│   ├── appendonly.aof
│   └── dump.rdb
└── default-data-redis-2-pvc-41dc4e4c-65fe-42cb-b41e-9117a0659eba
    ├── appendonly.aof
    └── dump.rdb

3 directories, 6 files



#验证
[root@small-master ~/yml/redis]# kubectl exec -it redis-0  -- bash
#查看主从信息
root@redis-0:/data# redis-cli 
127.0.0.1:6379> auth shuli@123
OK
127.0.0.1:6379> info Replication
# Replication
role:master
connected_slaves:2
slave0:ip=10.244.2.165,port=6379,state=online,offset=72640,lag=0
slave1:ip=10.244.1.31,port=6379,state=online,offset=72503,lag=0
master_replid:9531e163c328f057a33e37c9611bb828a2e077a3
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:72640
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:72640
127.0.0.1:6379> exit

#查看哨兵信息
root@redis-0:/data# redis-cli -p 26379
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=10.244.1.30:6379,slaves=2,sentinels=3

#连接redis

#K8S其他java程序连接redis哨兵
spring:
  redis:
    database: 4
    # redis哨兵地址
    sentinel:
      master: mymaster
      nodes: redis-0.redis.redis-demo.svc.cluster.local:26379,redis-1.redis.redis-demo.svc.cluster.local:26379,redis-2.redis.redis-demo.svc.cluster.local:26379
    # redis访问密码(默认为空)
    password: shuli@123

#客户端连接redis
node节点IP:32222 密码:shuli@123

2.2 mysql

secret资源使用:
[root@small-master ~/yml/zk-ka]# echo -n "shuli@123" |base64
c2h1bGlAMTIz
[root@small-master ~/yml/zk-ka]# echo "c2h1bGlAMTIz" |base64 -d
shuli@123[root@small-master ~/yml/zk-ka]#

#使用secret资源为mysql提供密码,这里注意,secret使用base64对原文加密。给密码加密是,需要使用echo -n不输出换行。否则传递过去的内容会有换行符,导致登录失败。
[root@small-master ~/yml/mysql]# cat mysql-secret.yml 
kind: Secret
apiVersion: v1
metadata:
  name: mysql-secret
data:
  MYSQL_ROOT_PASSWORD: c2h1bGlAMTIz
type: Opaque


#使用configmap资源挂载mysql配置文件
[root@small-master ~/yml/mysql]# cat mysql-cm.yml 
kind: ConfigMap
apiVersion: v1
metadata:
  name: mysql-cnf
data:
  custom.cnf: |-
    [mysqld]
    #performance setttings
    lock_wait_timeout = 3600
    open_files_limit    = 65535
    back_log = 1024
    max_connections = 512
    max_connect_errors = 1000000
    table_open_cache = 1024
    table_definition_cache = 1024
    thread_stack = 512K
    sort_buffer_size = 4M
    join_buffer_size = 4M
    read_buffer_size = 8M
    read_rnd_buffer_size = 4M
    bulk_insert_buffer_size = 64M
    thread_cache_size = 768
    interactive_timeout = 600
    wait_timeout = 600
    tmp_table_size = 32M
    max_heap_table_size = 32M
    
#创建headless供sts使用
[root@small-master ~/yml/mysql]# cat mysql-headless.yml 
kind: Service
apiVersion: v1
metadata:
  name: mysql-headless
  labels:
    app: mysql
spec:
  ports:
    - name: tcp-mysql
      protocol: TCP
      port: 3306
      targetPort: 3306
  selector:
    app: mysql
  clusterIP: None
  type: ClusterIP

#创建svc供外部访问
[root@small-master ~/yml/mysql]# cat mysql-svc.yml 
kind: Service
apiVersion: v1
metadata:
  name: mysql-external
  labels:
    app: mysql-external
spec:
  ports:
    - name: tcp-mysql-external
      protocol: TCP
      port: 3306
      targetPort: 3306
  selector:
    app: mysql
  type: NodePort
 
 
 #部署mysql有状态服务
[root@small-master ~/yml/mysql]# cat mysql-sts.yml 
kind: StatefulSet
apiVersion: apps/v1
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      volumes:
        - name: host-time
          hostPath:
            path: /etc/localtime
            type: ''
        - name: volume-cnf
          configMap:
            name: mysql-cnf
            items:
              - key: custom.cnf
                path: custom.cnf
            defaultMode: 420
      containers:
        - name: lstack-mysql
          image: 'harbor.ans.cn/saas/mysql:5.7.38'
          ports:
            - name: tcp-mysql
              containerPort: 3306
              protocol: TCP
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: MYSQL_ROOT_PASSWORD
          livenessProbe:
            tcpSocket:
              port: 3306
            initialDelaySeconds: 3
            periodSeconds: 5
          readinessProbe:
            tcpSocket:
              port: 3306
            initialDelaySeconds: 3
            periodSeconds: 5
          resources:
            limits:
              cpu: '1'
              memory: '2Gi'
            requests:
              cpu: '0.25'
              memory: '256Mi'
          volumeMounts:
            - name: host-time
              mountPath: /etc/localtime
            - name: data
              mountPath: /var/lib/mysql
            - name: volume-cnf
              mountPath: /etc/mysql/conf.d/custom.cnf
              subPath: custom.cnf
  serviceName: mysql-headless
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi
      storageClassName: managed-nfs-storage



#验证:
[root@small-master ~/yml/mysql]# kubectl exec -it mysql-0 bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
bash-4.2# mysql -uroot -pshuli@123
mysql: [Warning] Using a password on the command line interface can be insecure.
mysql> 

3. 暴露服务脚本

[root@small-master ~/yml/redis]# cat service.sh 
#!bin/bash
#auther:ans
#function:暴露集群服务端口
#脚本用法,需要指定服务名和服务端口号,名称空间默认是default,如果有名称空间需指定
service=$1
port=$2
namespace=${3:-default}


if [ ! $service ]; then
  echo "请输入第一个变量为pod名称关键字.如redis,kafka,mysql"
else
  if [ ! $port ]; then
     echo "请输入第二个变量为服务的端口号。如3306,6379"
  else
    for i in `kubectl get po -n $namespace |grep $service |awk '{print $1}'`
    do
      kubectl label pod -n $namespace  $i name=$i
      kubectl expose po -n $namespace  $i --port=$port --target-port=$port --name=$i --selector=name=$i --type=NodePort
    done
  fi
fi

#使用脚本

[root@small-master ~/yml/redis]# sh service.sh redis 6379 redis
pod/redis-0 labeled
service/redis-0 exposed
pod/redis-1 labeled
service/redis-1 exposed
pod/redis-2 labeled
service/redis-2 exposed

posted @ 2022-11-17 10:54  安生丶  阅读(475)  评论(0编辑  收藏  举报