0
点赞
收藏
分享

微信扫一扫

API资源对象Deployment;API资源对象Service;API资源对象DaemonSet;API资源对象StatefulSet

转角一扇门 2023-12-05 阅读 40

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)可能使用一种基于分区和副本的数据同步机制。

举报

相关推荐

0 条评论