美文网首页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