API资源对象Deployment;API资源对象Service;API资源对象DaemonSet;API资源对象StatefulSet
API资源对象Deployment;API资源对象Service;API资源对象DaemonSet;API资源对象StatefulSet
API资源对象Deployment
Deployment YAML示例:
vi ng-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: myng
name: ng-deploy
spec:
replicas: 2 ##副本数
selector:
matchLabels:
app: myng
template:
metadata:
labels:
app: myng
spec:
containers:
- name: myng
image: nginx:1.23.2
ports:
- name: myng-port
containerPort: 80
使用YAML创建deploy:
kubectl apply -f ng-deploy.yaml
查看:
kubectl get deploy
kubectl get po
查看pod分配到哪个节点上
kubectl get po -o wide
API资源对象Service
Service简称(svc) YAML示例:
vi ng-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: ngx-svc
spec:
selector:
app: myng
ports:
- protocol: TCP
port: 8080 ##service的port
targetPort: 80 ##pod的port
使用YAML创建service:
kubectl apply -f ng-svc.yaml
查看:
kubectl get svc
三种Service 类型:
1)ClusterIP
该方式为默认类型,即,不定义type字段时(如上面service的示例),就是该类型。
spec:
selector:
app: myng
type: ClusterIP
ports:
- protocol: TCP
port: 8080 ##service的port
targetPort: 80 ##pod的port
2)NodePort
如果想直接通过k8s节点的IP直接访问到service对应的资源,可以使用NodePort,Nodeport对应的端口范围:30000-32767
spec:
selector:
app: myng
type: NodePort
ports:
- protocol: TCP
port: 8080 ##service的port
targetPort: 80 ##pod的port
nodePort: 30009 ##可以自定义,也可以不定义,它会自动获取一个端口
3)LoadBlancer
这种方式,需要配合公有云资源比如阿里云、亚马逊云来实现,这里需要一个公网IP作为入口,然后来负载均衡所有的Pod。
spec:
selector:
app: myng
type: LoadBlancer
ports:
- protocol: TCP
port: 8080 ##service的port
targetPort: 80 ##pod的port
API资源对象DaemonSet
有些场景需要在每一个node上运行Pod(比如,网络插件calico、监控、日志收集),Deployment无法做到,而Daemonset(简称ds)可以。Deamonset的目标是,在集群的每一个节点上运行且只运行一个Pod。
Daemonset不支持使用kubectl create获取YAML模板,所以只能照葫芦画瓢了,参考Deployment的YAML编写,其实Daemonset和Deployment的差异很小,除了Kind不一样,还需要去掉replica配置。
vi ds-demo.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
app: ds-demo
name: ds-demo
spec:
selector:
matchLabels:
app: ds-demo
template:
metadata:
labels:
app: ds-demo
spec:
containers:
- name: ds-demo
image: nginx:1.23.2
ports:
- name: mysql-port
containerPort: 80
使用YAML创建ds
kubectl apply -f ds-demo.yaml
查看:
kubectl get ds
kubectl get po
但只在两个node节点上启动了pod,没有在master上启动,这是因为默认master有限制。
kubectl describe node k8s01 |grep -i 'taint'
Taints: node-role.kubernetes.io/control-plane:NoSchedule
说明:Taint叫做污点,如果某一个节点上有污点,则不会被调度运行pod。
但是这个还得取决于Pod自己的一个属性:toleration(容忍),即这个Pod是否能够容忍目标节点是否有污点。
为了解决此问题,我们可以在Pod上增加toleration属性。下面改一下YAML配置:
vi ds-demo.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
app: ds-demo
name: ds-demo
spec:
selector:
matchLabels:
app: ds-demo
template:
metadata:
labels:
app: ds-demo
spec:
tolerations:
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
containers:
- name: ds-demo
image: nginx:1.23.2
ports:
- name: mysql-port
containerPort: 80
再次应用此YAML
kubectl apply -f ds-demo.yaml
API资源对象StatefulSet
Pod根据是否有数据存储分为有状态和无状态:
- 无状态:指的Pod运行期间不会产生重要数据,即使有数据产生,这些数据丢失了也不影响整个应用。比如Nginx、Tomcat等应用适合无状态。
- 有状态:指的是Pod运行期间会产生重要的数据,这些数据必须要做持久化,比如MySQL、Redis、RabbitMQ等。
Deployment和Daemonset适合做无状态,而有状态也有一个对应的资源,那就是Statefulset(简称sts)。
说明:由于StatefulSet涉及到了数据持久化,用到了StorageClass,需要先创建一个基于NFS的StorageClass
额外开一台虚拟机,搭建NFS服务(具体步骤略)
假设NFS服务器IP地址为192.168.222.128,共享目录为/data/nfs
另外,要想使用NFS的sc,还需要安装一个NFS provisioner,它的作用是自动创建NFS的pv
github地址: https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner
将源码下载下来:
git clone https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner
cd nfs-subdir-external-provisioner/deploy
sed -i 's/namespace: default/namespace: kube-system/' rbac.yaml ##修改命名空间为kube-system
kubectl apply -f rbac.yaml ##创建rbac授权
修改deployment.yaml
sed -i 's/namespace: default/namespace: kube-system/' deployment.yaml ##修改命名空间为kube-system
##你需要修改标红的部分
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: chronolaw/nfs-subdir-external-provisioner:v4.0.2 ##改为dockerhub地址
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: k8s-sigs.io/nfs-subdir-external-provisioner
- name: NFS_SERVER
value: 192.168.222.128 ##nfs服务器地址
- name: NFS_PATH
value: /data/nfs ##nfs共享目录
volumes:
- name: nfs-client-root
nfs:
server: 192.168.222.128 ##nfs服务器地址
path: /data/nfs ##nfs共享目录
应用yaml
kubectl apply -f deployment.yaml
kubectl apply -f class.yaml ##创建storageclass
SC YAML示例
cat class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-client
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
archiveOnDelete: "false" ##自动回收存储空间
Sts示例:
vi redis-sts.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-sts
spec:
serviceName: redis-svc ##这里要有一个serviceName,Sts必须和service关联
volumeClaimTemplates:
- metadata:
name: redis-pvc
spec:
storageClassName: nfs-client
accessModes:
- ReadWriteMany
resources:
requests:
storage: 500Mi
replicas: 2
selector:
matchLabels:
app: redis-sts
template:
metadata:
labels:
app: redis-sts
spec:
containers:
- image: redis:6.2
name: redis
ports:
- containerPort: 6379
volumeMounts:
- name: redis-pvc
mountPath: /data
vi redis-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: redis-svc
spec:
selector:
app: redis-sts
ports:
- port: 6379
protocol: TCP
targetPort: 6379
应用两个YAML文件
kubectl apply -f redis-sts.yaml -f redis-svc.yaml
对于Sts的Pod,有如下特点:
① Pod名固定有序,后缀从0开始;
② “域名”固定,这个“域名”组成: Pod名.Svc名,例如 redis-sts-0.redis-svc;
③ 每个Pod对应的PVC也是固定的;
实验:
ping 域名
kubectl exec -it redis-sts-0 -- bash ##进去可以ping redis-sts-0.redis-svc 和 redis-sts-1.redis-svc
创建key
kubectl exec -it redis-sts-0 -- redis-cli
127.0.0.1:6379> set k1 'abc'
OK
127.0.0.1:6379> set k2 'bcd'
OK
模拟故障
kubectl delete pod redis-sts-0
删除后,它会自动重新创建同名Pod,再次进入查看redis key
kubectl exec -it redis-sts-0 -- redis-cli
127.0.0.1:6379> get k1
"abc"
127.0.0.1:6379> get k2
"bcd"
数据依然存在。
关于Sts里的多个Pod之间的数据同步
K8s并不负责Sts里的Pod间数据同步, 具体的数据同步和一致性策略取决于我们部署的有状态应用程序。不同的应用程序可能使用不同的数据同步和一致性策略。例如,关系型数据库(如 MySQL)可能使用主-从复制,而分布式数据库(如 MongoDB)可能使用一种基于分区和副本的数据同步机制。