《kubernetes-1.8.0》17-examples-Running ZooKeeper
《kubernetes 1.8.0 测试环境安装部署》
时间:2017-12-11
一、环境及基础知识准备:
在做zookeeper
这个样例之前,至少需要明白 StatefulSets, PodDisruptionBudgets,PodAntiAffinity,pv,pvc,storageclass等这些概念:
相关官网的doc:
- StatefulSets
- PodDisruptionBudgets
- PodAntiAffinity
- Persistent Volumes
- basic-stateful-set(tutorials)
- Dynamic Volume Provisioning
后续再文档中我也会做适当的说明:
环境需求:
- 至少4个节点的k8s集群
- 每个节点至少2CPUS 4G 内存
- 需配置了
Dynamic Volume Provisioning
特性,即,需配置了storageclass
。 - 如果没有配置
Dynamic Volume Provisioning
,则在创建StatefulSets
之前需要预先创建好对应的pvc
(20G)并bound。(特别说明:statefulset
用的是template
方式创建pvc,所以对应的pvc
名字是固定的,采用statefulsetname-volumename-number
方式命名,比如statefulset
名为zk,volume名字为datadir,rc为3:则需提前创建3个30G的pvc,名字分别为zk-datadir-0、zk-datadir-1、zk-datadir-2)
5.关于Dynamic Volume Provisioning
特性,之前已经做了本例中做部分修改:—> 《kubernetes-1.8.0》15-addon-vSphere Cloud Provider
环境准备中,部分修改内容如下:
创建缺省的storageclass
,即没有指定storageclassname
的请求都从这个storageclass
中划分资源:
创建缺省storageclass
:
default-sc.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
name: default
annotations: {
"storageclass.kubernetes.io/is-default-class" : "true"
}
provisioner: kubernetes.io/vsphere-volume
parameters:
diskformat: zeroedthick
datastore: local_datastore_47
reclaimPolicy: Retain
annotations
: 需指定storageclass.kubernetes.io/is-default-class
为true
,表明本sc 为 default sc:
开启apiserver支持:
在三台master上修改/etc/kubernetes/apiserver配置文件,ADMISSION_CONTROL字段中加入DefaultStorageClass字段:
重启apiserver:
$ systemctl daemon-reload
$ systemctl restart kube-apiserver
应用yaml:
$ kubectl create -f default-sc.yaml
查看所创建的StorageClass:
[root@node-131 zookeeper]# kubectl get sc
NAME PROVISIONER
default (default) kubernetes.io/vsphere-volume
fast kubernetes.io/vsphere-volume
- 此时应该看到创建的名字叫default的sc,后跟的(default)表明其为缺省sc;
至此基础环境大致完成了,这里多提醒一句,在做vsphere Volume Provisioning
尽量使用共享数据存储,如果使用主机数据存储那必须保证所有虚拟机在同一个数据存储之上,否则后续会导致部分pod无法挂载pvc的情况出现;
二、zookeeper 环境搭建及部分配置解读:
zookeeper.yaml
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/v1beta1
kind: PodDisruptionBudget
metadata:
name: zk-pdb
spec:
selector:
matchLabels:
app: zk
maxUnavailable: 1
---
apiVersion: apps/v1beta2 # for versions before 1.8.0 use apps/v1beta1
kind: StatefulSet
metadata:
name: zk
spec:
selector:
matchLabels:
app: zk
serviceName: zk-hs
replicas: 3
updateStrategy:
type: RollingUpdate
podManagementPolicy: Parallel
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: "gcr.mirrors.ustc.edu.cn/google_containers/kubernetes-zookeeper:1.0-3.4.10"
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
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
- 这个yaml文件中提供了4个部分的内容,两个
service
,一个PodDisruptionBudget
,一个StatefulSet
clusterIP: None
:表明是Headless Service
,statefulset
用固定的hostname进行解析(podname.servicename.namespace.svc.cluster.local.)
,继而绕过clusterIP
的虚地址负载均衡,直接访问到pod。PodDisruptionBudget
:是一个保护机制,其中确保了某个tag的pod实例的最小个数,因为想zk或者etcd这样的群集系统,为了防止管理员误操作或者autoscale缩容等使得pod实例数不满足最小条件,导致zk群集故障。比如该例子中设置标签是app: zk
的pod最大不可用数maxUnavailable
为1
。此时如果delete某一个pod是ok的,但是在这个pod恢复Running之前还想再delete一个则将被拒绝,因为….maxUnavailable
为1
;StatefulSet
:
podManagementPolicy: Parallel
:表示同时启动或者终止所有的pod,缺省为OrderedReady
表明必须按照顺序 0 ~ N-1启动spec.affinity
: 这个部分涉及亲和性部署,其中spec.affinity.podAntiAffinity
:表明是反亲和性部署requiredDuringSchedulingIgnoredDuringExecution
表明了是hard方式,也就是必须遵循反亲和性部署原则;后续labelSelector
说明了只要看到某个节点上的pods中 app:这个标签中有 zk的都不在这个node上创建该pod。volumeClaimTemplates
:写的是一个pvc的申请模板,会自动的为每个pod申请10G的pvc;- 特别说明:如果没有设置缺省的
StorageClass
,需在volumeClaimTemplates
中指定storageClassName
:声明从哪个StorageClass
中创建pvc。
加载yaml
$ kubectl apply -f zookeeper.yaml
查看pvc是否创建并bound
[root@node-131 zookeeper]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
...
datadir-zk-0 Bound pvc-fc2918cf-dd83-11e7-8e94-005056bc80ed 10Gi RWO default 18h
datadir-zk-1 Bound pvc-fc2ac19e-dd83-11e7-8e94-005056bc80ed 10Gi RWO default 18h
datadir-zk-2 Bound pvc-fc2c2889-dd83-11e7-8e94-005056bc80ed 10Gi RWO default 18h
...
- 注意看pvc name的规律
查看pod运行情况
kubectl get pods -w -l app=zk
NAME READY STATUS RESTARTS AGE
zk-0 0/1 Pending 0 0s
zk-0 0/1 Pending 0 0s
zk-0 0/1 ContainerCreating 0 0s
zk-0 0/1 Running 0 19s
zk-0 1/1 Running 0 40s
zk-1 0/1 Pending 0 0s
zk-1 0/1 Pending 0 0s
zk-1 0/1 ContainerCreating 0 0s
zk-1 0/1 Running 0 18s
zk-1 1/1 Running 0 40s
zk-2 0/1 Pending 0 0s
zk-2 0/1 Pending 0 0s
zk-2 0/1 Contain