赞
踩
前言
环境准备
部署NFS
部署StorageClass存储类(动态制备 PersistentVolume)
部署ZooKeeper
ZooKeeper健康检查
ZooKeeper是一个用于维护配置信息、命名、提供分布式同步和提供组服务的集中式服务。所有这些类型的服务都以某种形式被分布式应用程序使用。每次实现它们时,都要做大量的工作来修复不可避免的错误和竞争条件。由于实现这些类型的服务很困难,应用程序最初通常会吝啬它们,这使得它们在发生更改时很脆弱,很难管理。即使操作正确,在部署应用程序时,这些服务的不同实现也会导致管理的复杂性。
在ZooKeeper Wiki上了解更多关于ZooKeeper。
NFS:网络文件系统,英文Network File System(NFS),是由SUN公司研制的UNIX表示层协议(presentation layer protocol),能使使用者访问网络上别处的文件就像在使用自己的计算机一样。
StorageClass存储类:(简称SC)
介绍:StorageClass 为管理员提供了描述存储 “类” 的方法。 不同的类型可能会映射到不同的服务质量等级或备份策略,或是由集群管理员制定的任意策略。 Kubernetes 本身并不清楚各种类代表的什么。这个类的概念在其他存储系统中有时被称为 “配置文件”。
创建PV有两种方法,第一种手动去写/创建PV的yaml文件,就叫做静态制备,如果遇到成百上千个需要创建PV的环境,那么对于集群管理员是一个耗时耗力的事情;现在使用sc存储类来进行动态制备。只需要管理员规定一个模板,PVC来遵循这个模板,那么就PV就会自动自动创建
本次文章采用动态制备
CPU架构 | 系统版本 | Docker版本 | K8S版本 |
---|---|---|---|
x86_64 | CentOS 7.8 | 19.03.12 | v1.19.9 |
yum install -y nfs-utils rpcbind
mkdir /root/nfs
chmod 777 /root/nfs
vim /etc/exports
#写入以下配置
/root/nfs *(rw,no_root_squash,no_all_squash,sync)
/root/nfs #代表共享的目录
* #代表不限制IP连接
rw #可进行读写
no_root_squash #NFS客户端使用root连接服务器端时,那么对于服务端共享目录也具有共享权限
no_all_squash #(默认)访问用户先与本机用户匹配,匹配失败后再映射为匿名用户或用户组
sync #文件写入的时候同时写入硬盘
systemctl start rpcbind
systemctl enable rpcbind #加入开机自启
systemctl start nfs
systemctl enable nfs
showmount -e localhost #localhost(指本机 127.0.0.1 的意思)
6. 通过其他服务器测试挂载nfs磁盘
yum install -y nfs-utils #下载nfs-utils
mkdir /test #创建要被挂载的目录
mount 10.64.95.18:/root/nfs/mysql /test #IP地址是nfs服务器地址和共享目录,后者是本机目录
注意:挂载端需要下载第一步中的:nfs-utils,不会挂载的时候会提示以下错误
由于Kubernetes没有NFS驱动,也默认不支持NFS类型的StorageClass,从而需要外部驱动并修改配置文件
vim /etc/kubernetes/manifests/kube-apiserver.yaml #打开apiserver的yaml文件
添加以下配置
- --feature-gates=RemoveSelfLink=false
然后通过cat命令能查到配置
因为是自动应用,可以不用重启apiserver,如果不生效就通过以下命令重启下apiserver
systemctl restart kubelet
下载外部的制备器(内部含镜像文件,可提前下载)
访问github,下载deployment.yaml和rbac.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: quay.io/external_storage/nfs-client-provisioner:latest #镜像 volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: nfs #可以按照自己的命名更改 - name: NFS_SERVER value: 10.10.10.60 #NFS服务器地址 - name: NFS_PATH value: /ifs/kubernetes #共享目录 volumes: - name: nfs-client-root nfs: server: 10.10.10.60 #NFS服务器地址 path: /ifs/kubernetes #共享目录 deployment.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 rbac.yaml
开始安装
kubectl apply -f rbac.yaml #yaml文件里包含命名空间,可根据自身情况修改
kubectl apply -f deployment.yaml #yaml文件里面的下载策略,建议修改为imagePullPolicy: IfNotPresent
查看制备器的状态
创建StorageClass
[root@ks8-master ~]# vim storageclass.yaml
[root@ks8-master ~]# cat storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: managed-nfs-storage
provisioner: nfs # 这个就是deployemnt的yaml文件中的环境变量:PROVISIONER_NAME
parameters:
archiveOnDelete: "false"
allowVolumeExpansion: true
[root@ks8-master ~]# kubectl apply -f storageclass.yaml
查看创建的StorageClass
测试
[root@ks8-master pvc]# vim auto-pvc.yaml #storageClassName要和刚才创建的storageClass一样 [root@ks8-master pvc]# cat pvc1.yaml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: aotu-pvc-test namespace: ggzj spec: accessModes: - ReadWriteMany resources: requests: storage: 20Gi storageClassName: managed-nfs-storage [root@ks8-master pvc]# kubectl apply -f auto-pvc.yaml persistentvolumeclaim/aotu-pvc-test created [root@ks8-master pvc]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE aotu-pvc-test Bound pvc-af12e765-3459-4b7a-acdb-744fb81b2bb5 20Gi RWX managed-nfs-storage 13s
删除测试PVC
[root@ks8-master pvc]# kubectl delete -f auto-pvc.yaml
persistentvolumeclaim "aotu-pvc-test" deleted
[root@ks8-master pvc]# kubectl get pv
注意:deployment的yaml文件的PROVISIONER_NAME的环境变量的值必须与StorageClass的yaml文件的provisioner的值对应
StorageClass的yaml文件的name值必须与PVC的yaml文件的storageClassName值对应
这里引用kubernetes的官方文档
apiVersion: v1 kind: Service metadata: name: zk-hs labels: app: zk spec: ports: - port: 2888 name: server - port: 3888 name: leader-election clusterIP: None selector: app: zk --- apiVersion: v1 kind: Service metadata: name: zk-cs labels: app: zk spec: ports: - port: 2181 name: client selector: app: zk #--- #apiVersion: policy/v1 #kind: PodDisruptionBudget #metadata: # name: zk-pdb #spec: # selector: # matchLabels: # app: zk # maxUnavailable: 1 --- apiVersion: apps/v1 kind: StatefulSet metadata: name: zk spec: selector: matchLabels: app: zk serviceName: zk-hs replicas: 3 updateStrategy: type: RollingUpdate podManagementPolicy: OrderedReady template: metadata: labels: app: zk spec: affinity: #节点亲和性必须要三个工作节点 podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: "app" operator: In values: - zk topologyKey: "kubernetes.io/hostname" containers: - name: kubernetes-zookeeper imagePullPolicy: Always image: "registry.k8s.io/kubernetes-zookeeper:1.0-3.4.10" #镜像拉取不下来可以按照下面注意里面的镜像 imagePullPolicy: IfNotPresent resources: requests: memory: "1Gi" cpu: "0.5" ports: - containerPort: 2181 name: client - containerPort: 2888 name: server - containerPort: 3888 name: leader-election command: - sh - -c - "start-zookeeper \ --servers=3 \ --data_dir=/var/lib/zookeeper/data \ --data_log_dir=/var/lib/zookeeper/data/log \ --conf_dir=/opt/zookeeper/conf \ --client_port=2181 \ --election_port=3888 \ --server_port=2888 \ --tick_time=2000 \ --init_limit=10 \ --sync_limit=5 \ --heap=512M \ --max_client_cnxns=60 \ --snap_retain_count=3 \ --purge_interval=12 \ --max_session_timeout=40000 \ --min_session_timeout=4000 \ --log_level=INFO" readinessProbe: exec: command: - sh - -c - "zookeeper-ready 2181" initialDelaySeconds: 10 timeoutSeconds: 5 livenessProbe: exec: command: - sh - -c - "zookeeper-ready 2181" initialDelaySeconds: 10 timeoutSeconds: 5 volumeMounts: - name: datadir mountPath: /var/lib/zookeeper securityContext: runAsUser: 1000 fsGroup: 1000 volumeClaimTemplates: - metadata: name: datadir annotations: volume.beta.kubernetes.io/storage-class: "managed-nfs-storage" #managed-nfs-storage为我们创建的storage-class名称 spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 10Gi
注意:image中的镜像可能拉去不下来,请使用这个景象mirrorgooglecontainers/kubernetes-zookeeper:1.0-3.4.10
volume.beta.kubernetes.io/storage-class: "managed-nfs-storage" #这里面的storage-class的值必须为上述的storage-class名字
[root@ks8-master ~] kubectl apply -f zookeeper.yaml
service/zk-hs created
service/zk-cs created
statefulset.apps/zk created
Running
[root@ks8-master ~] kubectl get pods -w -l app=zk
NAME READY STATUS RESTARTS AGE
zk-0 1/1 Running 0 40s
zk-1 1/1 Running 0 40s
zk-2 1/1 Running 0 40s
(1) 使用命令 kubectl exec 获取 zk StatefulSet 中 Pod 的主机名。
StatefulSet 控制器基于每个 Pod 的序号索引为它们各自提供一个唯一的主机名。 主机名采用 <statefulset 名称>-<序数索引> 的形式。 由于 zk StatefulSet 的 replicas 字段设置为 3,这个集合的控制器将创建 3 个 Pod,主机名为:zk-0、zk-1 和 zk-2。
[root@ks8-master ~] for i in 0 1 2; do kubectl exec zk-$i -- hostname; done
zk-0
zk-1
zk-2
ZooKeeper ensemble 中的服务器使用自然数作为唯一标识符, 每个服务器的标识符都保存在服务器的数据目录中一个名为 myid 的文件里。
(2) 检查每个服务器的 myid 文件的内容。由于标识符为自然数并且序号索引是非负整数,你可以在序号上加 1 来生成一个标识符。
[root@ks8-master ~] 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
(3) 获取 zk StatefulSet 中每个 Pod 的全限定域名(Fully Qualified Domain Name,FQDN)
zk-hs Service 为所有 Pod 创建了一个域:zk-hs.default.svc.cluster.local。
[root@ks8-master ~] for i in 0 1 2; do kubectl exec zk-$i -- hostname -f; done
zk-0.zk-hs.default.svc.cluster.local
zk-1.zk-hs.default.svc.cluster.local
zk-2.zk-hs.default.svc.cluster.local
Kubernetes DNS 中的 A 记录将 FQDN 解析成为 Pod 的 IP 地址。 如果 Kubernetes 重新调度这些 Pod,这个 A 记录将会使用这些 Pod 的新 IP 地址完成更新, 但 A 记录的名称不会改变。
(4) ZooKeeper 在一个名为 zoo.cfg 的文件中保存它的应用配置。 使用 kubectl exec 在 zk-0 Pod 中查看 zoo.cfg 文件的内容。
文件底部为 server.1、server.2 和 server.3,其中的 1、2 和 3 分别对应 ZooKeeper 服务器的 myid 文件中的标识符。 它们被设置为 zk StatefulSet 中的 Pods 的 FQDNs。
[root@ks8-master ~] kubectl exec zk-0 -- cat /opt/zookeeper/conf/zoo.cfg
clientPort=2181
dataDir=/var/lib/zookeeper/data
dataLogDir=/var/lib/zookeeper/log
tickTime=2000
initLimit=10
syncLimit=2000
maxClientCnxns=60
minSessionTimeout= 4000
maxSessionTimeout= 40000
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
server.1=zk-0.zk-hs.default.svc.cluster.local:2888:3888
server.2=zk-1.zk-hs.default.svc.cluster.local:2888:3888
server.3=zk-2.zk-hs.default.svc.cluster.local:2888:3888
[root@ks8-master ~] kubectl exec zk-0 zkCli.sh create /hello world
最后会输出以下内容:
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
Created /hello
使用下面的命令从 zk-1 Pod 获取数据。
[root@ks8-master ~] kubectl exec zk-1 zkCli.sh get /hello
最后会消费以下内容:
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
world #获取内容
cZxid = 0x100000002
ctime = Thu Dec 08 15:13:30 UTC 2016
mZxid = 0x100000002
mtime = Thu Dec 08 15:13:30 UTC 2016
pZxid = 0x100000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。