Kubernetes实战与运维

1. Kubernetes实战

本实战案例拟使用Kubernetes平台部署一个WordPress博客系统,具体配置与介绍如下:

需要用到两个容器镜像,分别为wordpress:4.8-apache和mysql:5.6;使用NFS创建PV作为数据库与WordPress的后端存储;使用Secret生成器管理密码;最后使用yaml文件编排部署博客系统。

基础准备:

IP地址

主机名

节点

192.168.200.10

master

容器master节点

192.168.200.11

node

容器worker节点

一、基础环境安装与配置

        (一)安装与配置NFS

 在master节点上安装NFS所需要的软件及依赖,命令如下:

[root@k8s-master-node1 ~]# yum install -y nfs-utils rpcbind

安装完之后,启动RPC与NFS服务,命令如下:

[root@k8s-master-node1 ~]#systemctl start rpcbind

[root@k8s-master-node1 ~]# systemctl enable rpcbind

[root@k8s-master-node1 ~]#systemctl start nfs

[root@k8s-master-node1 ~]# systemctl enable nfs

创建/home/pvdata/mysql,/home/pvdata/wordpress两个目录,作为NFS的共享目录,然后赋予权限,命令如下:

[root@k8s-master-node1 ~]# mkdir -p /home/pvdata/mysql

[root@k8s-master-node1 ~]# mkdir -p /home/pvdata/wordpress

[root@k8s-master-node1 ~]# chmod 777 /home/pvdata/mysql  

[root@k8s-master-node1 ~]# chmod 777 /home/pvdata/wordpress

修改NFS配置文件/etc/exports,将创建的两个目录进行共享,命令如下:

[root@k8s-master-node1 ~]# vi /etc/exports

[root@k8s-master-node1 ~]# cat /etc/exports

#在/etc/exports配置文件中,添加如下两行

/home/pvdata/mysql 192.168.200.0/24(rw,no_root_squash,no_all_squash,sync,anonuid=501,anongid=501)

/home/pvdata/wordpress 192.168.200.0/24(rw,no_root_squash,no_all_squash,sync,anonuid=501,anongid=501)

    

生效NFS配置文件,并查看分享的目录,命令如下:

[root@k8s-master-node1 ~]# exportfs -r

[root@k8s-master-node1 ~]# showmount -e 192.168.200.10

Export list for 192.168.200.10:

/home/pvdata/wordpress 192.168.200.0/24

/home/pvdata/mysql     192.168.200.0/24

可以看创建的两个目录被共享了,NFS配置完毕。

(二)创建pv

     

在创建PV之前,首先创建一个工作目录,命令如下:

[root@k8s-master-node1 ~]# mkdir wordpress

[root@k8s-master-node1 ~]# cd wordpress/

[root@k8s-master-node1 wordpress]#

   

在wordpress目录下创建mysql-persistent-storage.yaml文件,该文件用来创建数据库使用的pv,文件内容如下:

[root@k8s-master-node1 wordpress]# cat mysql-persistent-storage.yaml

apiVersion: v1

kind: PersistentVolume

metadata:

  name: mysql-persistent-storage

spec:

    capacity:

      storage: 2Gi

    accessModes: ["ReadWriteMany","ReadWriteOnce"]

    persistentVolumeReclaimPolicy: Recycle

    nfs:

       path: /home/pvdata/mysql/

       server: 192.168.200.10

在wordpress目录下继续创建wordpress-persistent-storage.yaml文件,该文件用来创建WordPress使用的pv,文件内容如下:

[root@k8s-master-node1 wordpress]# cat wordpress-persistent-storage.yaml

apiVersion: v1

kind: PersistentVolume

metadata:

  name: wordpress-persistent-storage

spec:

    capacity:

      storage: 2Gi

    accessModes: ["ReadWriteMany","ReadWriteOnce"]

    persistentVolumeReclaimPolicy: Recycle

    nfs:

       path: /home/pvdata/wordpress/

       server: 192.168.200.10

编辑好yaml文件后,创建pv卷,命令如下:

[root@k8s-master-node1 wordpress]# kubectl apply -f mysql-persistent-storage.yaml

persistentvolume/mysql-persistent-storage created

[root@k8s-master-node1 wordpress]# kubectl apply -f wordpress-persistent-storage.yaml

persistentvolume/wordpress-persistent-storage created

创建完pv后,查看pv,命令如下:

[root@k8s-master-node1 wordpress]# kubectl get pv

NAME                           CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE

mysql-persistent-storage       2Gi        RWO,RWX        Recycle          Available                                   11s

wordpress-persistent-storage   2Gi        RWO,RWX        Recycle          Available                                   5s

可以看到两个pv都是Available的状态,pv创建成功。

(三)设置密码生成器

在/root/wordpress目录下创建kustomization.yaml文件,并在文件中添加一个Secret生成器,具体命令如下:

[root@k8s-master-node1 wordpress]# cat kustomization.yaml

secretGenerator:

- name: mysql-pass

  literals:

  - password=123456ok

(四)编辑yaml文件

首先在/root/wordpress目录下创建一个mysql-deployment.yaml文件,用来部署数据库服务,MySQL容器将PersistentVolume挂载在/var/lib/mysql。MYSQL_ROOT_PASSWORD环境变量设置来自Secret的数据库密码,mysql-deployment.yaml中的具体内容如下所示:

[root@k8s-master-node1 wordpress]# cat mysql-deployment.yaml

apiVersion: v1

kind: Service

metadata:

  name: wordpress-mysql

  labels:

    app: wordpress

spec:

  ports:

    - port: 3306

  selector:

    app: wordpress

    tier: mysql

  clusterIP: None

---

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  name: mysql-pv-claim

  labels:

    app: wordpress

spec:

  accessModes: ["ReadWriteOnce"]

  resources:

    requests:

      storage: 2Gi

---

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2

kind: Deployment

metadata:

  name: wordpress-mysql

  labels:

    app: wordpress

spec:

  selector:

    matchLabels:

      app: wordpress

      tier: mysql

  strategy:

    type: Recreate

  template:

    metadata:

      labels:

        app: wordpress

        tier: mysql

    spec:

      containers:

      - image: mysql:5.6

        name: mysql

        env:

        - name: MYSQL_ROOT_PASSWORD

          valueFrom:

            secretKeyRef:

              name: mysql-pass

              key: password

        ports:

        - containerPort: 3306

          name: mysql

        volumeMounts:

        - name: mysql-persistent-storage

          mountPath: /var/lib/mysql

      volumes:

      - name: mysql-persistent-storage

        persistentVolumeClaim:

          claimName: mysql-pv-claim

编辑好mysql-deployment.yaml之后,数据库的部署就告一段落了。还需要创建一个wordpress-deployment.yaml用来部署WordPress应用,WordPress容器网站数据文件位于/var/www/html。WORDPRESS_DB_HOST环境变量集上面定义了MySQL的Service名称,WordPress将通过Service访问数据库。WORDPRESS_DB_PASSWORD密码为Secret生成的数据库密码。具体文件内容如下:

[root@k8s-master-node1 wordpress]# cat wordpress-deployment.yaml

apiVersion: v1

kind: Service

metadata:

  name: wordpress

  labels:

    app: wordpress

spec:

  ports:

    - port: 80

      nodePort: 31000

  selector:

    app: wordpress

    tier: frontend

  type: NodePort

---

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  name: wp-pv-claim

  labels:

    app: wordpress

spec:

  accessModes: ["ReadWriteOnce"]

  resources:

    requests:

      storage: 2Gi

---

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2

kind: Deployment

metadata:

  name: wordpress

  labels:

    app: wordpress

spec:

  selector:

    matchLabels:

      app: wordpress

      tier: frontend

  strategy:

    type: Recreate

  template:

    metadata:

      labels:

        app: wordpress

        tier: frontend

    spec:

      containers:

      - image: wordpress:4.8-apache

        name: wordpress

        env:

        - name: WORDPRESS_DB_HOST

          value: wordpress-mysql

        - name: WORDPRESS_DB_PASSWORD

          valueFrom:

            secretKeyRef:

              name: mysql-pass

              key: password

        ports:

        - containerPort: 80

          name: wordpress

        volumeMounts:

        - name: wordpress-persistent-storage

          mountPath: /var/www/html

      volumes:

      - name: wordpress-persistent-storage

        persistentVolumeClaim:

          claimName: wp-pv-claim

可以注意到,此次部署的WordPress版本为wordpress:4.8-apache,该镜像在配套的软件包中提供,可自行上载到master节点。编辑完之后,保存退出,将以上两个文件补充到kustomization.yaml文件中,命令如下:

[root@k8s-master-node1 wordpress]# vi kustomization.yaml

[root@k8s-master-node1 wordpress]# cat kustomization.yaml

secretGenerator:

- name: mysql-pass

  literals:

  - password=123456ok

#在配置文件中添加如下代码

resources:

  - mysql-deployment.yaml

  - wordpress-deployment.yaml

kustomization.yaml包含用于部署WordPress网站的所有资源以及MySQL数据库。

二、部署应用

在/root/wordpress目录下,通过如下方式进行部署,命令如下:

[root@k8s-master-node1 wordpress]# kubectl apply -k ./

secret/mysql-pass-ccht6ddg2m created

service/wordpress-mysql created

service/wordpress created

deployment.apps/wordpress-mysql created

deployment.apps/wordpress created

persistentvolumeclaim/mysql-pv-claim created

persistentvolumeclaim/wp-pv-claim created

可以看到各类资源都被创建了,包括Service、Deployment、PVC等。查看Secret密码是否存在,命令如下:

[root@k8s-master-node1 wordpress]# kubectl get secret

NAME                    TYPE                       DATA   AGE

mysql-pass-ccht6ddg2m   Opaque                     1      5h2m

可以看到密码被成功创建,然后验证pv是否被成功挂载了,命令如下:

[root@k8s-master-node1 ~]# kubectl get pvc
NAME             STATUS   VOLUME                         CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mysql-pv-claim   Bound    mysql-persistent-storage       2Gi        RWO,RWX                       6d9h
wp-pv-claim      Bound    wordpress-persistent-storage   2Gi        RWO,RWX                       6d9h

可以看到创建的pv被挂载了。最后验证Service是否成功创建了,命令如下:

[root@k8s-master-node1 ~]# kubectl get svc
NAME              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes        ClusterIP   10.96.0.1      <none>        443/TCP        8d
wordpress         NodePort    10.96.236.54   <none>        80:31000/TCP   6d9h
wordpress-mysql   ClusterIP   None           <none>        3306/TCP       6d9h

也可以看到Service成功创建。在创建成功后,进行应用的验证。

通过浏览器访问http://192.168.200.10:31000

根据提示选择语言,并单击“Continue”按钮,进入配置信息界面。

根据要求填写相关信息,然后单击下方的“Install WordPress”按钮,进行安装,然后就可以进行登录了,使用自己设置的用户名和密码进行登录。

登录成功,部署wordpress应用成功。

2. Kubernetes运维

基础准备:

IP地址

主机名

节点

192.168.200.10

master

容器master节点

192.168.200.11

node

容器worker节点

使用这两台云主机作为实验基础环境。使用Kubeeasy工具先安装Kubernetes平台与Harbor平台。

一、Node的隔离与恢复

在硬件升级、硬件维护等情况下,需要将某些Node隔离。使用kubectl cordon <node_name>命令可禁止Pod调度到该节点上,在其上运行的Pod并不会自动停止,管理员需要手动停止在该Node上运行的Pod。因为此处使用的实操环境是一台,尝试停止将master节点隔离(master也是一个node节点),命令如下:

[root@k8s-master-node1 ~]# kubectl cordon k8s-master-node1

node/k8s-master-node1 cordoned

查看Node的状态,命令如下:

NAME               STATUS                     ROLES                         AGE   VERSION

k8s-master-node1   Ready,SchedulingDisabled   control-plane,master,worker   11d   v1.22.1

k8s-worker-node1   Ready                      worker                        11d   v1.22.1

可以观察到在node的状态中增加了一项SchedulingDisabled,对于后续创建的Pod,系统将不会再向该Node进行调度。

可以通过kubectl uncordon命令可完成对Node的恢复。命令如下:

[root@k8s-master-node1 ~]# kubectl uncordon k8s-master-node1

node/k8s-master-node1 uncordoned

再次查看Node信息,命令如下:

[root@k8s-master-node1 ~]# kubectl get nodes

NAME               STATUS   ROLES                         AGE   VERSION

k8s-master-node1   Ready    control-plane,master,worker   11d   v1.22.1

k8s-worker-node1   Ready    worker                        11d   v1.22.1

可以看到Node节点已恢复调度,STATUS又变成了Ready,允许Pod调度到该节点上。

通过kubectl drain <node_name>命令可实现对Node节点的驱逐,该命令会删除该节点上的所有Pod(DaemonSet除外)。

二、Pod动态扩容和缩放

在实际生产系统中,经常会遇到某个服务需要扩容的场景,也可能会遇到由于资源紧张或者工作负载降低而需要减少服务实例数量的场景。此时可以利用kubectl scale deployment命令来完成这些任务。

以Nginx Deployment为例,创建一个Nginx的Deployment,副本数为1,命令如下(在做该案例时,为了避免Kubernetes实战中创建的资源影响,可自行删除):

[root@k8s-master-node1 ~]# kubectl create deployment nginx --image=192.168.200.43/library/nginx:latest

deployment.apps/nginx created

查看Pod和Deployment,命令如下:

[root@k8s-master-node1 ~]# kubectl get pods

NAME                     READY   STATUS    RESTARTS   AGE

nginx-67cfb9b95d-sxt58   1/1     Running   0          3s

[root@k8s-master-node1 ~]# kubectl get deployment

NAME    READY   UP-TO-DATE   AVAILABLE   AGE

nginx   1/1     1            1           8s

通过使用scale命令将Nginx Deployment控制的Pod副本数量从初始的1更新为5。命令如下:

[root@k8s-master-node1 ~]# kubectl scale deployment nginx --replicas=5

deployment.apps/nginx scaled

更新副本后,继续查看Pod数量,命令如下:

[root@k8s-master-node1 ~]# kubectl get pods

NAME                            READY   STATUS    RESTARTS   AGE

nginx-674ff86d-7xgct            1/1     Running   0          66s

nginx-674ff86d-9mzvx            1/1     Running   0          66s

nginx-674ff86d-dw6mb            1/1     Running   0          66s

nginx-674ff86d-n6jqq            1/1     Running   0          4m33s

nginx-674ff86d-ztm8j            1/1     Running   0          66s

可以看到此时Nginx的Pod数量为5。调整副本数成功。如果需要将副本的数量调小,可以将--replicas设置为比当前Pod副本数量更小的数字,系统将会“杀掉”一些运行中的Pod,即可实现应用集群缩容。例如将Nginx的Pod副本数调整为3,命令如下:

[root@k8s-master-node1 ~]# kubectl scale deployment nginx --replicas=3

deployment.apps/nginx scaled

查看Pod数量,命令如下:

[root@k8s-master-node1 ~]# kubectl get pods

NAME                           READY   STATUS    RESTARTS   AGE

nginx-674ff86d-9mzvx           1/1     Running   0          4m56s

nginx-674ff86d-dw6mb           1/1     Running   0          4m56s

nginx-674ff86d-n6jqq           1/1     Running   0          8m23s

可以看到Pod副本数减少为3,验证Pod动态扩容和缩放实验成功。

三、将Pod调度到指定的Node

Kubernetes的Scheduler服务(kube-scheduler进程)负责实现Pod的调度,整个调度过程通过执行一系列复杂的算法最终为每个Pod计算出一个最佳的目标节点,这一过程是自动完成的,用户无法知道Pod最终会被调度到哪个节点上。有时可能需要将Pod调度到一个指定的Node上。此时,可以通过Node的标签(Label)和Pod的nodeSelector属性相匹配,来达到上述目的。

Label(标签)作为用户可灵活定义的对象属性,在已创建的对象上,仍然可以随时通过kubectl label命令对其进行增加、修改、删除等操作。使用kubectl label给node打标签的用法如下:

# kubectl label nodes <node-name> <label-key>=<label-value>

该案例需要起码两个Node节点。使用当前安装Kubernetes平台的master和node节点(主机名分别为k8s-master-node1和k8s-worker-node1),然后进行下述操作。

为node节点打上一个project=gcxt的标签。命令如下:

[root@k8s-master-node1 ~]# kubectl label nodes k8s-worker-node1 project=gcxt

node/k8s-worker-node1 labeled

如果想删除Label,只需要在命令行最后指定Label的key名,并加一个减号即可。

[root@k8s-master-node1 ~]# kubectl label nodes k8s-worker-node1 project-

node/k8s-worker-node1 labeled

在Pod中加入nodeSelector定义,示例如下。

[root@k8s-master-node1 ~]# cat nginx.yaml

apiVersion: v1

kind: ReplicationController

metadata:

  name: nginx-gcxt

  labels:

    name: nginx-gcxt

spec:

  replicas: 1

  selector:

    name: nginx-gcxt

  template:

    metadata:

      labels:

        name: nginx-gcxt

    spec:

      containers:

      - name: nginx-gcxt

        image: nginx:latest

        - containerPort: 80

      nodeSelector:

        project: gcxt

运行kubectl apply -f命令创建Pod,scheduler就会将该Pod调度到拥有project=gcxt标签的Node上去。

[root@k8s-master-node1 ~]# kubectl apply -f nginx.yaml

replicationcontroller/nginx-gcxt created

查看Pod的详细信息。命令如下:

[root@k8s-master-node1 ~]# kubectl get pods -owide

NAME                   READY   STATUS    RESTARTS   AGE   IP          NODE   NOMINATED NODE   READINESS GATES

nginx-gcxt-hdt5x   1/1     Running   0          14s   10.24.9.2   k8s-worker-node1   <none>           <none>

可以看到,Pod已成功调度到指定的Node节点。

四、应用滚动升级

当集群中的某个服务需要升级时,需要停止目前与该服务相关的所有Pod,然后重新拉取镜像并启动。如果集群规模比较大,这个工作就变成了一个挑战。如果采取先全部停止,然后逐步升级的方式,会导致较长时间的服务不可用。Kubernetes提供了rolling-update(滚动升级)功能来解决上述问题。

滚动升级通过执行kubectl rolling-update命令一键完成,该命令创建了一个新的Deployment,然后自动控制旧的Deployment中的Pod副本数量逐渐减少到0,同时新的Deployment中的Pod副本数量从0逐步增加到目标值,最终实现了Pod的升级。

注意:系统要求新的Deployment需要与旧的Deployment在相同的命名空间(Namespace)内,即不能把别人的资产偷偷转移到自家名下。

下面的示例在第一次部署时使用httpd:2.2.31,然后使用滚动升级更新到httpd:2.2.32。

首先定义yaml文件,在/root目录下创建httpd.yaml文件,文件内容如下所示:

[root@k8s-master-node1 ~]# vi httpd.yaml

[root@k8s-master-node1 ~]# cat httpd.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: httpd

spec:

  selector:

    matchLabels:

      app: httpd

  replicas: 3

  template:

    metadata:

      labels:

        app: httpd

    spec:

      containers:

        - name: httpd

          image: httpd:2.2.31

          ports:

          - containerPort: 80

创建httpd的Deployment,命令如下:

[root@k8s-master-node1 ~]# kubectl apply -f httpd.yaml

deployment.apps/httpd created

查看Pod和Deployment信息,命令如下:

[root@k8s-master-node1 ~]# kubectl get pod

NAME                           READY   STATUS    RESTARTS   AGE

httpd-745bddc8fb-7h9cr         1/1     Running   0          9m22s

httpd-745bddc8fb-h2s2p         1/1     Running   0          9m22s

httpd-745bddc8fb-wtx8r         1/1     Running   0          9m22s

[root@k8s-master-node1 ~]# kubectl get deployment -o wide

NAME              READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES                             SELECTOR

httpd             3/3     3            3           16m     httpd        httpd:2.2.31                       app=httpd

可以看到images的版本是2.2.31,修改httpd.yaml文件,把配置文件中的httpd:2.2.31改为httpd:2.2.32,如下所示:

[root@master ~]# vi httpd.yaml

[root@master ~]# cat httpd.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: httpd

spec:

  selector:

    matchLabels:

      app: httpd

  replicas: 3

  template:

    metadata:

      labels:

        app: httpd

    spec:

      containers:

        - name: httpd

          image: httpd:2.2.32

          ports:

          - containerPort: 80

再次启动Deployment,命令如下:

[root@k8s-master-node1 ~]# kubectl apply -f httpd.yaml

deployment.apps/httpd configured

再次查看Deployment的信息,命令如下:

[root@k8s-master-node1 ~]# kubectl get deployment -o wide

NAME              READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES                             SELECTOR

httpd             3/3     3            3           16m     httpd        httpd:2.2.32                       app=httpd

可以看到当前的httpd版本为2.2.32,查看Deployment的详细信息,命令如下:

[root@k8s-master-node1 ~]# kubectl describe deployment httpd

Name:                   httpd

Namespace:              default

CreationTimestamp:      Mon, 27 Sep 2021 11:20:28 -0400

Labels:                 <none>

Annotations:            deployment.kubernetes.io/revision: 2

Selector:               app=httpd

Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable

StrategyType:           RollingUpdate

MinReadySeconds:        0

RollingUpdateStrategy:  25% max unavailable, 25% max surge

Pod Template:

  Labels:  app=httpd

  Containers:

   httpd:

    Image:        httpd:2.2.32

    Port:         80/TCP

    Host Port:    0/TCP

    Environment:  <none>

    Mounts:       <none>

  Volumes:        <none>

Conditions:

  Type           Status  Reason

  ----           ------  ------

  Available      True    MinimumReplicasAvailable

  Progressing    True    NewReplicaSetAvailable

OldReplicaSets:  <none>

NewReplicaSet:   httpd-55d897fbfc (3/3 replicas created)

Events:

  Type    Reason             Age   From                   Message

  ----    ------             ----  ----                   -------

  Normal  ScalingReplicaSet  10m   deployment-controller  Scaled up replica set httpd-745bddc8fb to 3

  Normal  ScalingReplicaSet  18s   deployment-controller  Scaled up replica set httpd-55d897fbfc to 1

  Normal  ScalingReplicaSet  16s   deployment-controller  Scaled down replica set httpd-745bddc8fb to 2

  Normal  ScalingReplicaSet  16s   deployment-controller  Scaled up replica set httpd-55d897fbfc to 2

  Normal  ScalingReplicaSet  14s   deployment-controller  Scaled down replica set httpd-745bddc8fb to 1

  Normal  ScalingReplicaSet  14s   deployment-controller  Scaled up replica set httpd-55d897fbfc to 3

  Normal  ScalingReplicaSet  13s   deployment-controller  Scaled down replica set httpd-745bddc8fb to 0

上面的日志信息就描述了滚动升级的过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值