k8s

StatefulSet

Posted by qijun on January 12, 2022

有状态应用

1、拓扑状态:应用的多个实例之间不是完全对等的。这些应用实例必须按照某种顺序启动。并且,新创建出来的Pod必须和原来Pod的网络表示一致,这样原先的访问者才能使用同样的方法访问到这个新Pod。

2、存储状态:应用的多个实例分别绑定了不同的存储数据,他们之间应该保持固定的映射关系。

Service

Service是Kubernetes项目中用来将一组Pod暴露给外界访问的一种机制。有两种方式:

1、以VIP(virtual IP, 虚拟IP)方式

2、以DNS方式

其中DNS方式又分两种处理方式:

1、Normal Service。例如访问“my-svc.my-namespace.svc.cluster.local”解析到的正是my-svc的VIP

2、Headless Service。只需要配置spec.clusterIP: None即可。它所代理的所有Pod的IP地址都会被绑定到如下格式的DNS记录:

<pod-name>.<svc-name>.<namespace>.svc.cluster.local

固定拓扑状态

编写一个StatefulSet的YAML:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
    - port: 80
      name: web
  clusterIP: None
  selector:
    app: nginx

---

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.9.1
          ports:
            - containerPort: 80
              name: web
kubectl create -f svc.yaml

[root@master k8s]# kubectl get pods -w -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          53s
web-1   1/1     Running   0          34s
[root@slave ~]# kubectl run -i --tty --image busybox:1.28.3 dns-test --restart=Never --rm /bin/sh
If you don't see a command prompt, try pressing enter.
/ # nslookup web-0.nginx
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      web-0.nginx
Address 1: 10.32.0.2 web-0.nginx.default.svc.cluster.local
/ # nslookup web-1.nginx
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      web-1.nginx
Address 1: 10.36.0.3 web-1.nginx.default.svc.cluster.local

注意:这里busybox指定了版本,没有使用默认的最新版本。最新版本会报server can’t find web-0.nginx: NXDOMAIN,采坑指南——k8s域名解析coredns问题排查过程

通过这种方法,Kubernetes就成功地将Pod的拓扑状态,按照Pod的“名字+编号”的方式固定下来。此外,Kubernetes还为每一个Pod提供了一个固定且唯一的访问入口,即这个Pod对应的DNS记录。

固定存储状态

通过nfs的方式创建pv ,在此基础上,修改上节svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
    - port: 80
      name: web
  clusterIP: None
  selector:
    app: nginx

---

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.9.1
          ports:
            - containerPort: 80
              name: web
          volumeMounts:
            - name: www
              mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
    - metadata:
        name: www
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi

查看pvc

[root@master k8s]# kubectl get pvc
NAME        STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-web-0   Bound    pv000    1Gi        RWO                           28s
www-web-1   Bound    pv001    1Gi        RWO                           24s

验证

for i in 0 1; do kubectl exec web-$i -- sh -c 'echo hello $(hostname) > /usr/share/nginx/html/index.html'; done

for i in 0 1; do kubectl exec -it web-$i -- curl localhost; done

#我的nginx没有安装curl指令,所以kubectl describe pod web-0获取IP后直接在宿主机上
[root@master k8s]# curl 10.32.0.2
hello web-0
 
#删除Pod后验证html依然存在
[root@master k8s]# kubectl delete pod -l app=nginx
[root@master k8s]# curl 10.32.0.2
hello web-0

总结:
StatefulSet的控制器直接管理的是Pod
Kubernetes通过Headless Service为这些有编号的Pod,在DNS服务器中生成带有相同编号的DNS记录
StatefulSet还为每一个Pod分配并创建一个相同编号的PVC

Mysql集群实战

k8s-mysql-cluster

kubectl label nodes master mysql=master
kubectl label nodes slave mysql=slave
mkdir -p /mnt/mysql
kubectl create namespace data

systemctl status kubelet -l #查看报错日志
journalctl -xe #查看报错日志