kubernetes学习笔记 (二):k8s初体验

本文采用本地k8s v1.10.3版本开发,若是尚未搭建可参照 kubernetes学习笔记 (一):搭建本地k8s开发环境进行搭建node

搭建本地Docker镜像仓库

  1. docker pull docker.io/registry 拉取registry的镜像到本机
  2. docker run -d -p 5000:5000 --name=registry --restart=always --privileged=true --log-driver=none -v /home/data/registrydata:/tmp/registry registry 运行刚刚拉取的registry
  3. 在Docker for Mac中找到Docker -> Preferences -> Daemon,在insecure registries中填入本身刚刚搭建的本地仓库 http://localhost:5000

准备一个Docker镜像

  1. 随意使用什么语言写一个http接口,例如Nodejs:
@Get('whoami')
    async whoAmI() {
        debug('whoAmI called with %O', {});

        return { serverType: Config.SERVER_TYPE };
    }
复制代码
  1. 编写对应的DockerFile
FROM node:8
WORKDIR /root

RUN mkdir -p /root/app

COPY package.json /root/app/
COPY dist /root/app/dist

WORKDIR /root/app

RUN npm config set registry https://registry.npm.taobao.org/ ;\
    npm config set disturl https://npm.taobao.org/dist/ ;\
    npm i --production

CMD [ "node", "/root/app/dist/main.js" ]

EXPOSE 80

复制代码
  1. 编译、打标签,并推送到本地仓库中
echo 'Building to dits ...'
tsc

echo 'Docker building image ...'
docker build --rm -t localhost:5000/gateapp:0.0.1 .

echo 'Pushing ...'
docker push localhost:5000/gateapp

echo 'Docker list images ...'
docker images
复制代码

最后你会看到localhost:5000/gateapp:0.0.1的镜像已经在你的机器中啦,下面会用到docker

Kubernetes中的重要概念

  1. Cluster: Cluster是计算、存储和网络资源的集合,Kubernetes利用这些资源运行各类基于容器的应用
  2. Master: Master是Kubernetes的大脑,它的主要职责是调度,即决定将应用放在那里运行。
  3. Node: Node的职责是运行容器应用。Node由Master管理,Node负责监控并汇报容器的状态,同时根据Master的要求管理容器的生命周期。
  4. Pod: Pod是Kubernetes中最小工做单元。每一个Pod包含一个或多个容器。Pod中的容器会做为一个总体被Master调度到一个Node上运行。
  5. Controller:Kubernetes一般不会直接建立Pod,而是经过Controller来管理Pod。Controller中定义了Pod的部署特性,好比有几个副本、在什么样的Node上运行等。为了知足不一样的业务场景,Kubernetes提供了多种Controller,包括Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job等,后面会逐个学习这些Controller
  6. Service:Service定义外界访问一组特定Pod的方式。

建立Deployment部署应用

  1. 新建一个yaml文件,如:
apiVersion: extensions/v1beta1 # kubectl api的版本
kind: Deployment # kubernetes的资源类型
metadata:
    name: gate-deployment-dev
spec:
    replicas: 2 # 运行的Pod副本数量
    template:
        metadata:
            labels:
                app: gate-app-dev
        spec:
            containers:
                - name: gateapp
                  image: localhost:5000/gateapp:0.0.1 # Docker镜像地址(上面建立的)
                  env: # 镜像启动时的环境变量
                      - name: NODE_ENV
                        value: 'development'
                      - name: HTTP_PORT
                        value: '80' # 容器http的端口 须要本身代码中实现
复制代码
  1. 经过kubectl apply -f xxx.yaml就能够部署上面的Deployment的了,也能够打开Kubernetes的Dashboard点击建立,输入yaml文件中的内容进行建立。通过一段时间后,在Dashboard面板中能够看到,1个部署 gate-deployment-dev,一个副本集 gate-deployment-dev-775d556ffb,两个容器组 gate-deployment-dev-775d556ffb-2tlgn、gate-deployment-dev-775d556ffb-sfqrq,能够点击查看每一个资源的信息,大部份内容都是自解释的。数据库

    在部署Deployment后,Kubernetes大体执行了如下几个过程:npm

    • 用户建立Deployment
    • Deployment建立了一个副本集(ReplicaSet)gate-deployment-dev-775d556ffb
    • ReplicaSet建立了两个Pod,与咱们定义的replicas: 2 一致

建立Service

此时上面的镜像提供的接口还不能供外界访问,须要建立一个对应的Servicejson

  1. 新建立一个yaml文件或者在上一个yaml文件中添加 --- 隔开
  2. 编辑如下内容:
apiVersion: v1 # kubectl api的版本
kind: Service # kubernetes的资源类型
metadata:
    name: gate-svc-dev
spec:
    type: NodePort # service的类型 ClusterIp类型 只有Cluster内部节点和Pod能够访问 NodePort Cluster外部能够经过<NodeIp>:<NodePort>访问 LoadBalancer负载均衡
    selector:
        app: gate-app-dev # 与上面的template中定义的label一致
    ports:
        - protocol: TCP # 只有TCP 或 UDP
          port: 80 # clusterIp 监听的端口
          nodePort: 30000 # Node 监听的端口取值范围 30000-32767
          targetPort: 80 # Pod 监听的端口
复制代码
  1. kubectl apply -f xxx.yaml 或者在Dashboard中建立api

  2. 观察Dashboard面板,会发现多了一个名字叫gate-svc-dev的服务,提供了监听了30000端口安全

  3. curl http://localhost:30000/whoami 能够看到接口已经能够访问了bash

    须要注意的是:网络

    • 为何须要Service?app

      Deployment等其余Controller动态建立和销毁Pod来保证应用的健壮性,也就是Pod是脆弱的,应用是健壮的,咱们不应指望Pod的健壮性。每一个Pod都有本身的ClusterIp地址,当Pod发生故障被新的Pod替代时,ClusterIp颇有可能发生变化,因此若是直接让外界访问Pod就有问题了。

    • Service和Pod如何映射?

      经过上面的yaml定义能够看出,Service经过 label标签选择器选择对应的一堆Pod。当请求被发送到Service上时,Service采用了某种分配策略把流量转发到了某一个Pod上面进行处理。

    • Service有哪些类型?

      1. ClusterIp:Service经过Cluster内部的IP对外提供服务,只有Cluster内的节点和Pod能够访问,这是默认的类型。
      2. NodePort: Service经过Cluster节点的静态端口对外提供服务。Cluster外部能够经过<NodeIp>:<NodePort>访问Service
      3. LoadBalancer: cloud provider特有的对外提供服务,后续线上部署时会讲到

滚动更新

滚动更新是一次只更新一小部分副本,成功后再更新更多的副本,最终完成全部副本的更新。滚动更新最大的好处就是零停机,保证了业务的连续性。

  1. 对本地代码进行一点改动
  2. 编译、打标签,并推送到本地仓库中
echo 'Building to dits ...'
tsc

echo 'Docker building image ...'
docker build --rm -t localhost:5000/gateapp:0.0.2 .

echo 'Pushing ...'
docker push localhost:5000/gateapp

echo 'Docker list images ...'
docker images
复制代码

这时候能够看到有0.0.1 和 0.0.2两个版本的镜像

  1. 在Dashboard中编辑Deployment,把image: localhost:5000/gateapp:0.0.1改为image: localhost:5000/gateapp:0.0.2,点击更新

  2. 等待一段时间,再观察全部的Pod都被更新成0.0.2版本的了,是否是很方便!

    反复执行上面的步骤,不难发现更新过程当中Kubernets都作了什么:

    • Deployment的镜像被更新为0.0.2版本
    • 新建立了一个名称为gate-deployment-dev-594468997c的ReplicaSet副本集,镜像为0.0.2
    • 新的ReplicaSet增长了一个Pod
    • 旧的ReplicaSet减小了一个Pod
    • 逐渐的新的ReplicaSet接管了全部旧ReplicaSet的Pod,滚动更新完成
  3. 自定义滚动更新行为

strategy:
        rollingUpdate: # 滚动更新策略
            maxSurge: 10% # 数值越大 滚动更新时新建立的副本数量越多
            maxUnavailble: 10% # 数值越大 滚动更新时销毁的旧副本数量越多
    replicas: 2 # 运行的Pod副本数量
复制代码
- maxSurge:此参数控制滚动更新中副本总数超过DESIRED的数量或最大比例,数值越大 滚动更新时新建立的副本数量越多
- maxUnavailble:此参数控制滚动更新中,不可用的副本占DESIRED的最大数量或最大利弊,数值越大 滚动更新时销毁的旧副本数量越多
复制代码

那若是更新过程出错了怎么办?请接着往下看

健康检查

Kubernetes有很强大的自愈能力,默认的实现方式是重启发生故障的容器,此外用户可使用Liveness、 Readiness的探测机制设置更为精细的健康检查,进而真正实现零停机部署、避免部署无效的镜像、更加安全的滚动升级

  1. 编辑以前的Deployment.yaml,例如:
image: localhost:5000/gateapp:0.0.13
                  readinessProbe: # 一种健康检查决定是否加入到service 对外服务
                      httpGet:
                          scheme: HTTP # 支持http https
                          path: /healthy
                          port: 80 # 与你的pod端口一致
                      initialDelaySeconds: 10 # 容器启动多久后开始检查
                      periodSecods: 5 # 几秒检查一次
复制代码
  • readinessProbe便是使用Readiness健康探测机制,当检查不经过时(例如接口返回的状态码不是200-400之间),Kubernetes就不会把容器添加到Service中供外界访问,观察Pod的状态为Not Ready。 initialDelaySeconds是决定容器启动多久后开始检查,一般要比启动时间再长一些;periodSecods是多久检查一次,连续3次探测失败后,Ready将变成不可用,Kubernets把这个Pod从Service中下线

  • LiveNess的配置项和Readiness的同样,不一样之处在于探测失败后的行为。前者会重启容器,后者会设置Pod不可用,并从Service中下线。

  • LiveNess和Readiness的探测是独立使用的,两者没有依赖,能够单独使用也能够同时使用。通常状况下使用LiveNess判断容器是否须要重启实现自愈;Readiness判断容器是否已经准备好对外提供服务。

  1. 自定义健康检查的代码: 自定义/healthy get接口,好比数据库链接等等
@Get('healthy')
    async checkHealthy(@Res() res: Response) {
        let isHealthy = false;

        // some code to check healthy begin
        isHealthy = true;
        // check end

        const data = {
            isHealthy,
        };

        debug('执行健康检查结果 %O', data);

        res.status(isHealthy ? HttpStatus.OK : HttpStatus.INTERNAL_SERVER_ERROR).json(data);
    }
复制代码

一块儿来学习Kubernetes

相信看完以上的文章,你也会认为Kubernetes真的很是强大,是很是值得学习的。笔者也是小白一个,从0开始学习的,若是你也想一块儿,能够加入咱们的群。

相关文章
相关标签/搜索