在k8s中新建一个nginx服务demo

在k8s中新建一个nginx服务

这个示例中,我们会在一个pod中封装一个nginx的镜像,然后通过deploy发布出来,并通过service暴露对外访问的接口

在新版本的kubernetes中,引入了deployment对象,作为pod对象的管理器。通过deployment对象,可以实现pod的自动重启、状态监测等任务的自动化管理。

线上应用都应该使用deployment来管理应用

在集群的管理服务器上新建/root/k8s-tutorial目录,后面的示例中的配置文件,我们均会在该目录下存储。
新增/root/k8s-tutorial/0-base目录,用来存储本示例中的文件。

  • (1)新增deploy配置文件,并创建deploy

新建deploy-nginx.yaml文件,并写入如下内容:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    app: test-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test-nginx
  template:
    metadata:
      labels:
        app: test-nginx
    spec:
      containers:
      - name: test-nginx
        image: registry-vpc.cn-beijing.aliyuncs.com/rsq-public/nginx:1.13.12
        ports:
        - containerPort: 80

该模板可以直接从阿里云上拷贝。需要注意的几点是:

  • metadata.labels:是deployment的label,用于标记这个deployment
  • spec.replicas:该deployment包含的pod副本的数量
  • spec.selector.matchLabels:必须与spec.template.metadata.labels中能匹配上
  • spec.template:表示deployment包含的单个pod的配置
  • spec.template.metadata.labels:必须与spec.selector.matchLabels对应上,这样才能与deployment关联上
  • spec.template.spec.containers:单个pod的所包含的所有镜像的配置
  • spec.template.spec.containers[0].name:pod中第一个镜像的名称
  • spec.template.spec.containers[0].image:pod中第一个镜像使用的镜像地址及版本
  • spec.template.spec.containers[0].ports:pod中第一个镜像需要对外映射的端口列表
  • spec.template.spec.containers[0].ports[0].containerPort:与Dockerfile中暴露的端口对应

通过kubectl create -f deploy-nginx.yaml在当前的namespace下创建一个deploy

通过kubectl get deploy,可以查看deploy
通过kubectl get pod,可以查看deploy中的pod

当deploy的结果中AVAILABLE的数量与DESIRED的数量一致时,表示deploy部署成功

  • (2)新增service配置文件,并创建service

新建service-nginx.yaml文件,并写入如下内容:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: test-nginx
spec:
  selector:
    app: test-nginx
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
  type: NodePort

该模板可以直接从阿里云上拷贝。需要注意的几点是:

  • metadata.labels:表示这个Service的标签
  • spec.selector:service关联的pod的label,与deployment中template配置中的label一致
  • spec.type:默认的配置上ClusterI,只能在集群内部访问,不能外网访问NodePort表示将pod的端口映射到Node上。
  • spec.ports[0].port:service在集群内访问的端口
  • spec.ports[0].targetPort:pod中容器镜像的端口
  • spec.ports[0].nodePort:pod中的端口映射到node机器中的端口,如果不指定,k8s会随机一个端口,范围默认是30000-32767,如果指定,端口范围推荐也在30000-32767范围内。

通过kubectl get service,可以查看service

  • (3)集群外访问

由于我们设置了Service的type为NodePort,因此可以直接在集群的node服务器上访问,即在集群外访问。直接在任意一台机器上访问localhost:30080都可以访问到nginx服务。如果出现无法访问的情况,可以通过以下方式查看:

  • 依次检查service/deploy/pod是否都运行正常
  • 使用kubectl log命令(后面会具体讲)查看日志
  • 使用kubectl exec命令进入容器内部查看,与docker exec命令类似。例如:

kubectl exec -it [podName] bash

  • (4)集群内访问

在集群内部,我们可以通过内部域名的方式来访问服务。这种方式性能更好,推荐在集群内部使用这种方式。

默认域名结构:

[serviceName].[namespace].svc.cluster.local

例如:“test” namespace下的"test-nginx" service,可以通过test-nginx.test.svc.cluster.local访问

演示如下:

首先通过kubectl get pod命令查询出当前运行的pod名称

然后通过kubectl exec -it [podName] bash进入到容器内,即进入到集群内部环境中

可以使用ping test-nginx.test.svc.cluster.local命令查看

  • (4)删除nginx服务

删除服务时,使用kubectl delete -f [fileName]的方式

kubectl delete -f service-nginx.yaml

kubectl delete -f deploy-nginx.yaml

给nginx服务限定资源配额

新增/root/k8s-tutorial/1-resources目录,用来存储本示例中的文件。

  • (1)新增service配置文件,并创建service

新建service-nginx.yaml文件,并写入如下内容:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: test-nginx
spec:
  selector:
    app: test-nginx
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
  type: NodePort

运行命令kubectl create -f service-nginx.yaml,创建service

  • (2)新增deploy配置文件,并创建deploy

新建deploy-nginx.yaml文件,并写入如下内容:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    app: test-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test-nginx
  template:
    metadata:
      labels:
        app: test-nginx
    spec:
      containers:
      - name: test-nginx
        image: registry-vpc.cn-beijing.aliyuncs.com/rsq-public/nginx:1.13.12
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "50m"
          limits:
            memory: "128Mi"
            cpu: "100m"

说明:

  • spec.template.spec.containers[0].resources.requests:初始请求所需的资源
  • spec.template.spec.containers[0].resources.requests.memory:初始请求所需的内存资源
  • spec.template.spec.containers[0].resources.requests.cpu:初始请求所需的cpu资源
  • spec.template.spec.containers[0].resources.limits:可以使用的资源的限制
  • spec.template.spec.containers[0].resources.limits.memory:可以使用的内存资源的限制
  • spec.template.spec.containers[0].resources.limits.cpu:可以使用的cpu资源的限制

内存的单位MiGi分别表示1M和1G。对于一般的java程序,至少需要2Gi的空间
cpu的单位为m,一核cpu为1000m,以此类推

运行命令kubectl create -f deploy-nginx.yaml,创建deploy

  • (3)查看资源限额

运行命令kubectl get pod -o wide,获得pod所在的node的nodeName

运行命令kubectl describe node [nodeName]查看pod的资源占用

  • (4)删除nginx服务

kubectl delete -f service-nginx.yaml

kubectl delete -f deploy-nginx.yaml

给nginx指定liveness和readiness探针

新增/root/k8s-tutorial/2-probe目录,用来存储本示例中的文件。

  • (1)新增service配置文件,并创建service

新建service-nginx.yaml文件,并写入如下内容:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: test-nginx
spec:
  selector:
    app: test-nginx
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
  type: NodePort

运行命令kubectl create -f service-nginx.yaml,创建service

  • (2)新增deploy配置文件,并创建deploy

新建deploy-nginx.yaml文件,并写入如下内容:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    app: test-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test-nginx
  template:
    metadata:
      labels:
        app: test-nginx
    spec:
      containers:
      - name: test-nginx
        image: registry-vpc.cn-beijing.aliyuncs.com/rsq-public/nginx:1.13.12
        ports:
        - containerPort: 80
        livenessProbe:
          httpGet:
            path: /task/css/page.css
            port: 8080
          initialDelaySeconds: 360
          timeoutSeconds: 5
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /task/css/page.css
            port: 8080
          initialDelaySeconds: 120
          timeoutSeconds: 5
          periodSeconds: 5

说明:

  • spec.template.spec.containers[0].ivenessProbe:存活探针,用来检测应用是否存活,如果检测失败,pod将会被自动重启
  • spec.template.spec.containers[0].ivenessProbe.httpGet.path:http请求检测的路径
  • spec.template.spec.containers[0].ivenessProbe.httpGet.port:http请求检测的端口
  • spec.template.spec.containers[0].ivenessProbe.initialDelaySeconds:项目刚启动时,在多少秒内不进行存活检测
  • spec.template.spec.containers[0].ivenessProbe.timeoutSeconds:超时时间,应用响应时间超过这个时间将会被判定检测失败
  • spec.template.spec.containers[0].ivenessProbe.periodSeconds:检测周期,检测开始后,每隔多长时间进行一次检测
  • spec.template.spec.containers[0].eadinessProbe:启动检测,用来检测应用是否可以对外提供服务,如果检测失败,应用将不会被分配流量
  • spec.template.spec.containers[0].eadinessProbe.httpGet.path:http请求检测的路径
  • spec.template.spec.containers[0].eadinessProbe.httpGet.port:http请求检测的端口
  • spec.template.spec.containers[0].eadinessProbe.initialDelaySeconds:项目启动(或被重启)时,在多少秒内不进行检测
  • spec.template.spec.containers[0].eadinessProbe.timeoutSeconds:超时时间,应用响应时间超过这个时间将会被判定检测失败
  • spec.template.spec.containers[0].eadinessProbe.periodSeconds:检测周期,检测开始后,每隔多长时间进行一次检测

特别注意的有以下几点:

  • 存活检测的initialDelaySeconds:这个值应该视具体应用的启动时间而定,应该比应用预估的最长启动时间再大一些。对于java应用,假设启动时间在180s(3分钟左右),而存活检测的initialDelaySeconds如果设置为60s,那么60s内探针无法检测成功,会强制应用重启。这样导致的结果是应用反复重启而不能正常启动!
  • 存活检测的periodSeconds:这个值不宜过长,过长会导致应用已经宕了,但是迟迟没有重启恢复
  • 启动检测的initialDelaySeconds:这个值应该略小于应用的预估启动时间,保证一旦项目启动成功,可以及时检测到。

运行命令kubectl create -f deploy-nginx.yaml,创建deploy

启动时,可以观察鉴活探针和启动探针的具体表现

  • (3)删除nginx服务

kubectl delete -f service-nginx.yaml

kubectl delete -f deploy-nginx.yaml

使用persistent volume

persistent volume(简写为pv)是对存储介质的抽象。存储介质包括:硬盘、NAS盘、NFS存储等。对于演示类的项目,可以使用本地磁盘作为pv,而在线上环境中,推荐使用云服务商的NAS、OSS等分布式存储作为pv

以下以阿里云的NAS为例,建立pv

persistent volume claim(简写为pvc)是对镜像与pv的连接的抽象。

新增/root/k8s-tutorial/3-pv目录,用来存储本示例中的文件。

  • (1)新增service配置文件,并创建service

新建service-nginx.yaml文件,并写入如下内容:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: test-nginx
spec:
  selector:
    app: test-nginx
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
  type: NodePort

运行命令kubectl create -f service-nginx.yaml,创建service

  • (2)阿里云NAS中新增html文件

创建阿里云NAS服务,并挂载到ECS中,然后在其中创建/test-nginx-project/hello.html文件:

<!DOCTYPE html>
<html>
<head>
	<title>hello</title>
</head>
<body>
  hello world
</body>
</html>
  • (3)新增pv配置文件,并创建pv

新建pv-nginx.yaml文件,并写入如下内容:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: test-nginx-project-pv
spec:
  capacity:
    storage: 1M
  storageClassName: test-nginx-project-pv
  accessModes:
    - ReadOnlyMany
  flexVolume:
    driver: "alicloud/nas"
    options:
      server: "xxxxxxxxx-jog17.cn-beijing.nas.aliyuncs.com"
      path: "/test-nginx-project"
      vers: "4.0"
      mode: "755"

说明:

  • spec.capacity.storage:存储的空间大小
  • spec.storageClassName:存储的类,这个类会在pvc的定义中用到
  • spec.accessModes:读取的方式
  • spec.flexVolume.driver:pv驱动
  • spec.flexVolume.options.server:阿里云nas提供的nas server的地址
  • spec.flexVolume.options.path:nas中的映射的目录
  • spec.flexVolume.options.vers:阿里云nas的版本
  • spec.flexVolume.options.mode:阿里云nas中文件的mode

运行命令kubectl create -f pv-nginx.yaml,创建pv

运行命令kubectl get pv,查看创建的pv

  • (4)新增pvc配置文件,并创建pvc

新建pvc-nginx.yaml文件,并写入如下内容:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-nginx-project-pvc
spec:
  accessModes:
    - ReadOnlyMany
  storageClassName: test-nginx-project-pv
  resources:
    requests:
      storage: 1M

说明:

  • spec.accessModes:权限不能大于pv
  • spec.storageClassName:与pv对应的storageClass
  • spec.resources.requests.storage:请求的空间大小

运行命令kubectl create -f pvc-nginx.yaml,创建pvc

运行命令kubectl get pvc,查看创建的pvc

  • (5)新增deploy配置文件,并创建deploy

新建deploy-nginx.yaml文件,并写入如下内容:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    app: test-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test-nginx
  template:
    metadata:
      labels:
        app: test-nginx
    spec:
      containers:
      - name: test-nginx
        image: registry-vpc.cn-beijing.aliyuncs.com/rsq-public/nginx:1.13.12
        ports:
        - containerPort: 80
        volumeMounts:
        - name: base-project
          mountPath: /usr/share/nginx/html
      volumes:
      - name: base-project
        persistentVolumeClaim:
          claimName: test-nginx-project-pvc

说明:

  • spec.template.spec.volumes[0].name:引入的volume的名字
  • spec.template.spec.volumes[0].persistentVolumeClaim.claimName:引入的volume对应的pvc,需要与之前创建的pvc的name对应
  • spec.template.spec.containers[0].volumeMounts[0].name:与spec.template.spec.volumes[0].name对应
  • spec.template.spec.containers[0].volumeMounts[0].mountPath:映射到容器中的路径

需要注意的是映射到容器中的指定路径后,路径如果已存在,那么路径中的文件会全部丢失,只会加载pv中的文件

  • (6)测试

访问localhost:30080/hello.html可以成功返回页面

  • (7)删除nginx服务

kubectl delete -f service-nginx.yaml

kubectl delete -f deploy-nginx.yaml

kubectl delete -f pvc-nginx.yaml

kubectl delete -f pv-nginx.yaml

使用configmap外置配置文件

新增/root/k8s-tutorial/4-configmap目录,用来存储本示例中的文件。

  • (1)新增service配置文件,并创建service

新建service-nginx.yaml文件,并写入如下内容:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: test-nginx
spec:
  selector:
    app: test-nginx
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
  type: NodePort

运行命令kubectl create -f service-nginx.yaml,创建service

  • (2)新增configmap配置文件,并创建configmap

新建configmap-nginx.yaml文件,并写入如下内容:

apiVersion: v1
kind: ConfigMap
metadata:
  name: test-nginx-config
data:
  default.conf: |
    server {
        listen 80 default_server;
        server_name default_server;

        location / {
            proxy_pass https://www.rishiqing.com
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }

说明:

  • data:key值为挂载到容器内的文件名。value值为文件的内容。注意value值中关于yaml文件格式的处理。

运行命令kubectl create -f configmap-nginx.yaml,创建configmap

运行命令kubectl get configmap,查看configmap

  • (3)新增deploy配置文件,并创建deploy

新建deploy-nginx.yaml文件,并写入如下内容:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    app: test-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test-nginx
  template:
    metadata:
      labels:
        app: test-nginx
    spec:
      containers:
      - name: test-nginx
        image: registry-vpc.cn-beijing.aliyuncs.com/rsq-public/nginx:1.13.12
        ports:
        - containerPort: 80
        volumeMounts:
        - name: base-config
          mountPath: /etc/nginx/conf.d
      volumes:
      - name: base-config
        configMap:
          name: test-nginx-config

说明:

  • spec.template.spec.volumes[0].name:引入的volume的名字
  • spec.template.spec.volumes[0].configMap.name:引入的configmap的名称
  • spec.template.spec.containers[0].volumeMounts[0].name:与spec.template.spec.volumes[0].name对应
  • spec.template.spec.containers[0].volumeMounts[0].mountPath:映射到容器中的路径

运行命令kubectl create -f deploy-nginx.yaml,创建deploy

  • (4)测试

访问localhost:30080可以直接跳转到日事清

  • (4)删除nginx服务

kubectl delete -f service-nginx.yaml

kubectl delete -f deploy-nginx.yaml

kubectl delete -f configmap-nginx.yaml

secret基本操作

相对于configmap,secret会对其中的数据进行base64 hash存储。其用法与configmap类似,也可以映射通过volumeMounts挂载到容器中

  • (1)创建docker镜像仓库的密钥

kubectl create secret docker-registry [secretName] --docker-server=registry-vpc.cn-beijing.aliyuncs.com --docker-username=aaaa@xxx.com --docker-password=111111 --docker-email=hello@123.com

  • docker-registry:表示secret的类型,可以用来执行docker login

  • secretName:secret的名称

  • –docker-server:docker仓库的地址

  • –docker-username:登录用户名

  • –docker-password:登录密码

  • –docker-email:邮箱

  • (2)在拉取docker镜像时使用secret

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    app: test-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test-nginx
  template:
    metadata:
      labels:
        app: test-nginx
    spec:
      containers:
      - name: test-nginx
        image: registry-vpc.cn-beijing.aliyuncs.com/rsq-public/nginx:1.13.12
        ports:
        - containerPort: 80
      imagePullSecrets:
      - name: ali-docker

说明:

集群操作——deploy集群更新、伸缩与回滚

k8s集群中可以方便地进行更新、伸缩和回滚操作

查看容器运行日志

滚动显示一个pod的日志:

kubectl log -f [podName]

滚动显示一个pod的日志,且只显示后100行。由于输出的日志能比较多,因此--tail参数会很常用

kubectl log -f --tail=100 [podName]

当pod重启后,-p参数可以查看前一个pod的日志,从而查找pod重启的原因

kubectl log -p --tail=100 [podName]

集群更新

更新k8s中镜像版本:

kubectl set image deployment/[deployName] [containerName]=[imagePath]

说明:

  • deployName:deploy的名称

  • containerName:deploy的pod中的container的名称

  • imagePath:待更新的镜像的路径

  • (1)新建deploy

新建deploy-nginx.yaml文件,并写入如下内容:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    app: test-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test-nginx
  template:
    metadata:
      labels:
        app: test-nginx
    spec:
      containers:
      - name: test-nginx
        image: registry-vpc.cn-beijing.aliyuncs.com/rsq-public/nginx:1.13.12
        ports:
        - containerPort: 80
  • (2)更新image版本

kubectl set image deployment nginx-deploy test-nginx=registry-vpc.cn-beijing.aliyuncs.com/rsq-public/nginx:1.14

可以将nginx更新成1.14版本

通过命令kubectl describe deployment nginx-deploy可以查看是否更新到最新版本

集群回滚

  • (1)查看历史版本
    运行命令

kubectl rollout history deployment nginx-deploy

查看历史版本。如果要查看某个历史版本的详细信息,可以运行命令:

kubectl rollout history deployment nginx-deploy --revision=[revisionNumber]

其中[revisionNumber]为之前命令中查看到的版本号。在详细信息中可以看到具体的镜像版本

  • (2)将deploy回滚到之前的某个版本

kubectl rollout undo deployment nginx-deploy --to-revision=[revisionNumber]

其中[revisionNumber]为需要回滚到的版本

集群伸缩

将副本数量伸缩成1个:

kubectl scale deployment nginx-deploy --replicas=1

将应用发布到kubernetes中

由于kubernetes集群中的应用是无状态的,因此如果要将一个应用发布到kubernetes中,首先需要考虑以下几个方面:

  • 配置文件的存储方式。configmap/secret/pv
  • 日志文件的输出方式。pv/console/日志服务
  • 其他状态文件的存储,例如上传的文件等。pv/公共存储
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐