美文网首页0基础自学linux
0基础自学linux运维-3.9-k8s kubeadm Sta

0基础自学linux运维-3.9-k8s kubeadm Sta

作者: hualinux | 来源:发表于2019-07-30 00:28 被阅读0次

    一、环境说明

    系统centos7.6

    k8s:用kubeadm安装上k8s见我的文章 《0基础自学linux运维-3.8-Centos7 kubeadm1.14搭建k8s群集

    master:192.168.3.176

    node1:名字vm61 ip:192.168.3.61

    node1:名字vm62 ip:192.168.3.62

    二、StatefulSet理解

    一个应用的所有 Pod,是完全一样的。所以,它们互相之间没有顺序,也无所谓运行在哪台宿主机上。需要的时候,Deployment 就可以通过 Pod 模板创建新的 Pod;不需要的时候,Deployment 就可以“杀掉”任意一个 Pod。

      但是,在实际的场景中,并不是所有的应用都可以满足这样的要求。尤其是分布式应用,它的多个实例之间,往往有依赖关系,比如:主从关系、主备关系。

      还有就是数据存储类应用,它的多个实例,往往都会在本地磁盘上保存一份数据。而这些实例一旦被杀掉,即便重建出来,实例与数据之间的对应关系也已经丢失,从而导致应用失败。

      所以,这种实例之间有不对等关系,以及实例对外部数据有依赖关系的应用,就被称为“有状态应用”(Stateful Application)。

    StatefulSet 的设计其实非常容易理解。它把真实世界里的应用状态,抽象为了两种情况:

    1)拓扑状态:

      这种情况意味着,应用的多个实例之间不是完全对等的关系。这些应用实例,必须按照某些顺序启动,比如应用的主节点 A 要先于从节点 B 启动。而如果你把 A 和 B 两个 Pod 删除掉,它们再次被创建出来时也必须严格按照这个顺序才行。并且,新创建出来的 Pod,必须和原来 Pod 的网络标识一样,这样原先的访问者才能使用同样的方法,访问到这个新 Pod。

    2)存储状态

      这种情况意味着,应用的多个实例分别绑定了不同的存储数据。对于这些应用实例来说,Pod A 第一次读取到的数据,和隔了十分钟之后再次读取到的数据,应该是同一份,哪怕在此期间 Pod A 被重新创建过。这种情况最典型的例子,就是一个数据库应用的多个存储实例。

    所以,StatefulSet 的核心功能,就是通过某种方式记录这些状态,然后在 Pod 被重新创建时,能够为新 Pod 恢复这些状态。

    三、建立Headless Service

    Service被访问的2种方式:

    1. 第一种方式,是以 Service 的 VIP(Virtual IP,即:虚拟 IP)方式

    比如:当我访问 10.0.23.1 这个 Service 的 IP 地址时,10.0.23.1 其实就是一个 VIP,它会把请求转发到该 Service 所代理的某一个 Pod 上。这里的具体原理,我会在后续的 Service 章节中进行详细介绍。

    2.而在第二种 Service DNS 的方式下,具体还可以分为两种处理方法:

    1)第一种处理方法,是 Normal Service。这种情况下,你访问“my-svc.my-namespace.svc.cluster.local”解析到的,正是 my-svc 这个 Service 的 VIP,后面的流程就跟 VIP 方式一致了。

    2)而第二种处理方法,正是 Headless Service。这种情况下,你访问“my-svc.my-namespace.svc.cluster.local”解析到的,直接就是 my-svc 代理的某一个 Pod 的 IP 地址。

    所谓的 Headless Service,其实仍是一个标准 Service 的 YAML 文件。只不过,它的 clusterIP 字段的值是:None,即:这个 Service,没有一个 VIP 作为“头”。这也就是 Headless 的含义。所以,这个 Service 被创建后并不会被分配一个 VIP,而是会以 DNS 记录的方式暴露出它所代理的 Pod。

    3.1 建立Headless Service

    #即clusterIP: None的Service

    #编写部署(master节点)注意yaml空格要严格对,

    #本来是用mysql主从的,为了方便使用nginx,熟悉之后再改为mysql主从

    mkdir -pv /disk1/myk8s

    cd /disk1/myk8s/

    cd /disk1/myk8s/

    cat>nginx-ser-none.yaml<<EOF

    apiVersion: v1

    kind: Service

    metadata:

      name: nginx-ser-none

      labels:

        app: nginx-ser-none

    spec:

      selector:

        app: nginx2

      ports:

      - port: 80

        targetPort: 82

        # 这个名字需要

        name: web

        # nodePort: 30082

      # clusterIP: None 时,不能用 nodePort属性

      clusterIP: None

    EOF

    kubectl apply -f nginx-ser-none.yaml --record

    注:

    targetPort: 80,这样就会找取“app=nginx”且端口为80的pod

    Service中的clusterIP: 一定要为None,即clusterIP: None

    当你按照这样的方式创建了一个 Headless Service 之后,它所代理的所有 Pod 的 IP 地址,都会被绑定一个这样格式的 DNS 记录,如下所示:

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

    3.2 建立StatefulSet的yaml

    在这里我不用Deployment的RS(Replicas)我这里用StatefulSet

    #node vm61上操作

    mkdir -pv /disk1/www/t1

    echo "vm61 index.html" >/disk1/www/t1/index.html

    #node vm62上操作:

    mkdir -pv /disk1/www/t1

    echo "vm62 index.html" >/disk1/www/t1/index.html

    #在master端操作

    cat>nginx-statefulset.yaml<<EOF

    apiVersion: apps/v1

    kind: StatefulSet

    metadata:

      name: web

    spec:

      serviceName: "nginx-ser-none"

      replicas: 3

      selector:

        matchLabels:

          app: nginx2

      template:

        metadata:

          labels:

            app: nginx2

        spec:

          containers:

          - name: nginx2

            image: nginx:1.15.12

            ports:

            - containerPort: 82

              name: nginx2

            volumeMounts:

            - mountPath: /usr/share/nginx/html

              name: test-volume

          volumes:

          - name: test-volume

            hostPath:

              # directory location on host

              path: /disk1/www/t1

    EOF

    #--record 的 flag 设置为 true可以在 annotation 中记录当前命令创建或者升级了该资源

    #我推荐你使用 kubectl apply 命令,来统一进行 Kubernetes 对象的创建和更新操作

    #kubectl create -f nginx-statefulset.yaml --record

    kubectl apply -f nginx-statefulset.yaml --record

    #因为没用到部署和无状态的rs,所以为空

    [root@vm176 myk8s]# kubectl get po

    NAME    READY  STATUS    RESTARTS  AGE

    web-0  1/1    Running  0          39s

    web-1  1/1    Running  0          31s

    web-2  1/1    Running  0          26s

    [root@vm176 myk8s]# kubectl get deployments

    No resources found.

    [root@vm176 myk8s]# kubectl get rs

    No resources found.

    [root@vm176 myk8s]# kubectl get pods --show-labels

    NAME    READY  STATUS    RESTARTS  AGE  LABELS

    web-0  1/1    Running  0          44s  app=nginx,controller-revision-hash=web-6bc58d48c5,statefulset.kubernetes.io/pod-name=web-0

    web-1  1/1    Running  0          36s  app=nginx,controller-revision-hash=web-6bc58d48c5,statefulset.kubernetes.io/pod-name=web-1

    web-2  1/1    Running  0          31s  app=nginx,controller-revision-hash=web-6bc58d48c5,statefulset.kubernetes.io/pod-name=web-2

    [root@vm176 disk1]# kubectl get statefulsets

    NAME  READY  AGE

    web    3/3    5m15s

    3.3 更新nginx版本

    #根据hub.docker.com搜索nginx知道最新版本为1.16.0

    #也可以使用 kubectl edit deployment/nginx-deployment

    kubectl set image statefulsets/web nginx=nginx:1.16

    #如果是用apply命令创建的,可以直接修改nginx-deployment.yaml,再执行apply -f生效

    sed -i '/nginx:1.15.12/s/1.15.12/1.16/' nginx-statefulset.yaml

    grep 'nginx:' nginx-statefulset.yaml

    kubectl apply -f nginx-statefulset.yaml

    #按ctrl+c退出

    [root@vm176 myk8s]# kubectl get pods -w -l app=nginx2

    NAME    READY  STATUS    RESTARTS  AGE

    web-0  1/1    Running  0          4m7s

    web-1  1/1    Running  0          4m20s

    web-2  1/1    Running  0          4m27s

    四、测试statefulSet

    4.1查看一下主机名

    [root@vm176 myk8s]# kubectl exec web-0  hostname

    web-0

    [root@vm176 myk8s]# kubectl exec web-1  hostname

    web-1

    [root@vm176 myk8s]# kubectl exec web-2  hostname

    web-2

    ##看到没有,web-0、web-1、web-2永远是固定不变的,hostname永远不变,只有IP才变

    ##所以不能通过IP访问,只能通过DNS

    4.2 分析pod dns

    #用nslookup测试一下

    yum install bind-utils -y

    #尝试直接使用主机名访问

    [root@vm176 myk8s]# nslookup web-0

    Server: 192.168.128.2

    Address: 192.168.128.2#53

    ** server can't find web-0: REFUSED

    上面分析其中192.168.128.2是服务器的DNS,我这里用的是网关,所以跑出网关去查找这个主机名了,明显没有找到的

    [root@vm176 myk8s]# kubectl run -i --tty --image busybox:1.28 dns-test --restart=Never --rm /bin/sh

    If you don't see a command prompt, try pressing enter.

    / # nslookup web-0

    Server:    10.96.0.10

    Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

    nslookup: can't resolve 'web-0'

    容器内访问也不行,查看官网pod dns规则

    根据pod dns规则

    得知:以下ns为Namespace意思

    Service (ns/name):default/nginx-ser-none

    StatefulSet (ns/name):default/web

    Hostname:web-{0..N-1}我这里只查看web-0

    StatefulSet Domain格式为

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

    Pod DNS Pod格式为:

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

    例如web-0

    web-0.nginx-ser-none.default.svc.cluster.local

    #查看 nslookup <svc-name>

    #从上面知道访问web-0的pod dns为web-0.nginx-ser-none.default.svc.cluster.local

    可以通过内部访问nginx,内部端口为80(虽然我指定了容器端口为82,但是还是默认用80)

    我这里我们可以理解成,用statefulset建立的容器可以通过一个容器内部访问到它

    我这里我建立一个nginx容器,statefulset建立的web-0、web-1、web-2做后端服务器,nginx做前端

    4.3 用deployment建立一个容器,为了访问我这里rs用2个

    #分别在vm61和vm62执行

    mkdir -pv /disk1/k8sConf/nginx-lb

    cd /disk1/myk8s/

    cat>nginx-deployment.yaml<<EOF

    apiVersion: apps/v1beta1

    kind: Deployment

    metadata:

      name: nginx-deployment

    spec:

      replicas: 3

      template:

        metadata:

          labels:

            app: nginx

        spec:

          containers:

          - name: nginx

            image: nginx:1.16

            ports:

            - containerPort: 80

    EOF

    #创建服务

    cat>nginx-ser.yaml<<EOF

    apiVersion: v1

    kind: Service

    metadata:

      name: nginx-ser

      labels:

        app: nginx-ser

    spec:

      type: NodePort

      selector:

        app: nginx

      ports:

      - port: 80

        #port of pod

        targetPort: 80

        #nodePort: 30080

      clusterIP: 10.100.0.80

      externalIPs:

        - 192.168.3.176

    EOF

    kubectl apply -f nginx-deployment.yaml --record

    kubectl apply -f nginx-ser.yaml --record

    #查看是否下载完

    [root@vm176 myk8s]# kubectl get pod

    NAME                                READY  STATUS    RESTARTS  AGE

    nginx-deployment-66f9f9cfd5-stp74  1/1    Running  0          2m36s

    nginx-deployment-66f9f9cfd5-tlh84  1/1    Running  0          2m36s

    web-0                              1/1    Running  0          48m

    web-1                              1/1    Running  0          40m

    web-2                              1/1    Running  0          39m

    [root@vm176 myk8s]#

    curl -s 10.100.0.80

    #修改nginx配置,做成前端代理方式

    kubectl exec nginx-deployment-66f9f9cfd5-stp74 cat /etc/nginx/conf.d/default.conf >>default.conf

    vim default.conf

    #修改成如下格式

    upstream k8s_ngx {

      server web-0.nginx-ser-none.default.svc.cluster.local:80  weight=1;

      server web-1.nginx-ser-none.default.svc.cluster.local:80  weight=1;

      server web-2.nginx-ser-none.default.svc.cluster.local:80  weight=1; 

    }

    server {

        listen      80;

        server_name  localhost;

        #charset koi8-r;

        #access_log  /var/log/nginx/host.access.log  main;

        location / {

            proxy_pass http://k8s_ngx;

        }

    ...

    }

    #把刚才设置好的nginx配置文件分别弄到vm61和vm62中的disk1/k8sConf/nginx-lb目录下

    scp default.conf root@192.168.3.61:/disk1/k8sConf/nginx-lb

    scp default.conf root@192.168.3.62:/disk1/k8sConf/nginx-lb

    #修改一下nginx-deployment.yaml文件

    cat>nginx-deployment.yaml<<EOF

    apiVersion: apps/v1beta1

    kind: Deployment

    metadata:

      name: nginx-deployment

    spec:

      replicas: 3

      template:

        metadata:

          labels:

            app: nginx

        spec:

          containers:

          - name: nginx

            image: nginx:1.16

            ports:

            - containerPort: 80

            volumeMounts:

            - mountPath: /etc/nginx/conf.d/

              name: test-volume

          volumes:

          - name: test-volume

            hostPath:

              # directory location on host

              path: /disk1/k8sConf/nginx-lb

    EOF

    #应用修改

    kubectl apply -f nginx-deployment.yaml

    #打开浏览器访问,不断按F5刷新发现在

    http://192.168.3.176

    #在master主机上访问

    [root@vm61 nginx-lb]# curl 10.100.0.80

    vm61 index.html

    [root@vm61 nginx-lb]# curl 10.100.0.80

    vm61 index.html

    [root@vm61 nginx-lb]# curl 10.100.0.80

    vm62 index.html

    说明成功了

    相关文章

      网友评论

        本文标题:0基础自学linux运维-3.9-k8s kubeadm Sta

        本文链接:https://www.haomeiwen.com/subject/pxomrctx.html