从docker到istio之三 - kubernetes集群编排

栏目: 编程工具 · 发布时间: 5年前

内容简介:容器化,云原生越演越烈,新概念非常之多。信息爆炸的同时,带来层层迷雾。我尝试从扩容出发理解其脉路,经过实践探索,整理形成一个入门教程,包括下面四篇文章。这是第三篇,kubernetes编排应用。Kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。

容器化,云原生越演越烈,新概念非常之多。信息爆炸的同时,带来层层迷雾。我尝试从扩容出发理解其脉路,经过实践探索,整理形成一个入门教程,包括下面四篇文章。

这是第三篇,kubernetes编排应用。

kubernetes

Kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。

Kubernetes在希腊语中意思是船长或领航员,这也恰好与它在容器集群管理中的作用吻合,即作为装载了集装箱(Container)的众多货船的指挥者,负担着全局调度和运行监控的职责。因为Kubernetes在k和s之间有8个字母,所以又简称k8s

快速体验k8s,可以使用Docker for mac中集成的k8s。

从docker到istio之三 - kubernetes集群编排

启动k8s后,等待其初始化完成,然后 docker ps 可以看到k8s启动了一系列的容器:

CONTAINER ID        IMAGE                            COMMAND                  CREATED             STATUS              PORTS               NAMES
17a693617137        docker/kube-compose-controller   "/compose-controller…"   3 days ago          Up 3 days                               k8s_compose_compose-74649b4db6-szsqz_docker_4f5997b7-5c47-11e9-95b9-025000000001_0
a9b666b48815        docker/kube-compose-api-server   "/api-server --kubec…"   3 days ago          Up 3 days                               k8s_compose_compose-api-5d754cdd89-ncwrq_docker_131b4d65-04e7-11e9-837c-025000000001_0
f4b05eefc73a        6f7f2dc7fab5                     "/sidecar --v=2 --lo…"   3 days ago          Up 3 days                               k8s_sidecar_kube-dns-86f4d74b45-zh6qc_kube-system_f669bc59-04e6-11e9-837c-025000000001_0
867f8f040258        c2ce1ffb51ed                     "/dnsmasq-nanny -v=2…"   3 days ago          Up 3 days                               k8s_dnsmasq_kube-dns-86f4d74b45-zh6qc_kube-system_f669bc59-04e6-11e9-837c-025000000001_0
17f26a6e91d2        80cc5ea4b547                     "/kube-dns --domain=…"   3 days ago          Up 3 days                               k8s_kubedns_kube-dns-86f4d74b45-zh6qc_kube-system_f669bc59-04e6-11e9-837c-025000000001_0

...

复制代码

kubectl version 查看集群版本:

Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.11", GitCommit:"637c7e288581ee40ab4ca210618a89a555b6e7e9", GitTreeState:"clean", BuildDate:"2018-11-26T14:38:32Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.11", GitCommit:"637c7e288581ee40ab4ca210618a89a555b6e7e9", GitTreeState:"clean", BuildDate:"2018-11-26T14:25:46Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
复制代码

kubectl get nodes 查看k8s集群节点:

NAME                 STATUS    ROLES     AGE       VERSION
docker-for-desktop   Ready     master    123d      v1.10.11
复制代码

kubectl get service 查看k8s默认启动的服务:

NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   123d
复制代码

部署应用及测试

编写应用部署文件

1. flaskapp文件 k8s/flaskapp.yaml

apiVersion: v1
kind: Service
metadata:
  name: flaskapp
spec:
  ports:
    - port: 5000
  selector:
    name: flaskapp
---
apiVersion: extensions/v1beta1 
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    metadata:
      labels:
        name: flaskapp
    spec:
      containers:
      - image: flaskapp:0.0.2
        name: flaskapp
        ports:
        - containerPort: 5000
复制代码

了解这个部署文件,需要先大概了解一下k8s的运作方式。k8s通过api server提供restful接口,用于集群交互。每一个部署对象,都有 apiVersionkind , metadata , spec 这几个关键字。

  • 定义了Service和Deployment2个类型的对象。Service表示k8s对外提供的服务,Deployment表示某个service的部署方式。
  • Service对象的ports描述了服务端口,这个是集群内部网络的端口。
  • Service对象的selector描述了服务如何选择对于的部署,采用标签 name: flaskapp ,这是一种解耦合的依赖关系。
  • Deployment的replicas描述了容器的副本个数,下文会演示如何扩充。
  • Deployment的containers描述了镜像名称,服务端口等。

2. redis服务文件 k8s/redis.yaml

apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  ports:
    - port: 6379
  selector:
    name: redis
---
apiVersion: extensions/v1beta1 
kind: Deployment
metadata:
  name: redis
spec:
  replicas: 1
  template:
    metadata:
      labels:
        name: redis
    spec:
      containers:
      - image: redis:4-alpine3.8
        name: redis
        ports:
        - containerPort: 6379
复制代码

redis的部署文件和flaskapp的部署文件类似。

3. nginx服务文件 k8s/nginx.yaml

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-config
data:
  default.conf: |
    upstream flaskapp {
        server flaskapp:5000;
    }
    server {
        listen       80;
        server_name  localhost;

        root /usr/share/nginx/html;

        location / {
            proxy_pass http://flaskapp;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_redirect off;
        }

    }
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
    - port: 80
  selector:
    name: nginx
  type: NodePort
---
apiVersion: extensions/v1beta1 
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
      - image: nginx:1.15.8-alpine
        name: nginx
        ports:
        - containerPort: 80
        volumeMounts:
          - name: nginx-config-volume
            mountPath: /etc/nginx/conf.d/default.conf
            subPath: default.conf
      volumes:
        - name: nginx-config-volume
          configMap:
            name: nginx-config
复制代码

nginx的部署文件,变化在:

nginx\default.conf

部署应用到集群

使用 kubectl apply -f k8s 命令将编写yaml文件提交到k8s集群,集群会自动根据yaml文件的声明,进行部署。

service "flaskapp" created
deployment.extensions "flaskapp" created
configmap "nginx-config" created
service "nginx" created
deployment.extensions "nginx" created
service "redis" created
deployment.extensions "redis" created
复制代码

这里的 kubectl apply -f k8s 表示将k8s目录下的文件都提交给k8s集群。当然,也可以逐个文件提交 kubectl apply -f k8s/redis.yaml

访问应用

kubectl get service 检查一下k8s内的服务:

NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
flaskapp     ClusterIP   10.110.202.47    <none>        5000/TCP       31s
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP        123d
nginx        NodePort    10.100.233.149   <none>        80:30457/TCP   31s
redis        ClusterIP   10.106.55.214    <none>        6379/TCP       31s
复制代码

注意nginx服务部分的PORTS为 80:30457/TCP ,这表示将容器的80端口暴露到本机网络的30457端口,和我们之前的docker启动时候的 -p 80:80 参数类似。

服务是由Pod提供的,继续检查一下pods的状况 kubectl get pods :

NAME                        READY     STATUS    RESTARTS   AGE
flaskapp-6c4fccdf99-v6w2v   1/1       Running   0          2m
nginx-85fb469b96-lr982      1/1       Running   0          2m
redis-5b44bb8d97-wwmll      1/1       Running   0          2m
复制代码

当然,也可以直接查看docker的容器 docker ps :

➜  docker2istio docker ps
CONTAINER ID        IMAGE                            COMMAND                  CREATED             STATUS              PORTS               NAMES
ad7377ae7196        ae70b17240ec                     "docker-entrypoint.s…"   About an hour ago   Up About an hour                        k8s_redis_redis-5b44bb8d97-wwmll_default_2907f4a3-6639-11e9-b8cb-025000000001_0
c01108b49076        1a61773c4c07                     "python flaskapp.py"     About an hour ago   Up About an hour                        k8s_flaskapp_flaskapp-6c4fccdf99-xcmwb_default_28fbe1b1-6639-11e9-b8cb-025000000001_0
11d1fa3f182b        315798907716                     "nginx -g 'daemon of…"   About an hour ago   Up About an hour                        k8s_nginx_nginx-85fb469b96-lr982_default_28fbdeee-6639-11e9-b8cb-025000000001_0
c28032a4b068        k8s.gcr.io/pause-amd64:3.1       "/pause"                 About an hour ago   Up About an hour                        k8s_POD_redis-5b44bb8d97-wwmll_default_2907f4a3-6639-11e9-b8cb-025000000001_0
7091657acfbc        k8s.gcr.io/pause-amd64:3.1       "/pause"                 About an hour ago   Up About an hour                        k8s_POD_flaskapp-6c4fccdf99-xcmwb_default_28fbe1b1-6639-11e9-b8cb-025000000001_0
97007670c247        k8s.gcr.io/pause-amd64:3.1       "/pause"                 About an hour ago   Up About an hour                        k8s_POD_nginx-85fb469b96-lr982_default_28fbdeee-6639-11e9-b8cb-025000000001_0
...
复制代码

!!!注意: pod并不等同于docker的容器,Pod才是k8s操作的最小单元。简单的说,一个Pod可能包含多个容器,从yaml文件中 containers: 这个关键字可以看出。仔细观察 docker ps 的输出,可以发现每个pod除了用户自定义的容器外,还有镜像为 k8s.gcr.io/pause-amd64:3.1 的系统容器。

最后使用 curl http://127.0.0.1:30457 访问服务

Hello World by 10.1.0.21 from 192.168.65.3 ! 该页面已被访问 1 次。
复制代码

扩容

k8s集群下,扩容非常简单

➜  docker2istio kubectl edit deployment/flaskapp
deployment.extensions "flaskapp" edited
复制代码

修改其中的** replicas: 3 **。

也可以修改 k8s\flaskapp.yaml 中的值,然后 kubectl apply -f k8s\flaskapp.yaml

另外,如果镜像有更新,也是采用修改flaskapp.yaml文件然后apply的方式。

kubectl get pods -o wide 检查扩容结果, 这里使用了 -o wide ,可以显示更多信息

NAME                        READY     STATUS    RESTARTS   AGE       IP          NODE
flaskapp-6c4fccdf99-9xsjl   1/1       Running   0          3m        10.1.0.23   docker-for-desktop
flaskapp-6c4fccdf99-xcmwb   1/1       Running   0          1h        10.1.0.21   docker-for-desktop
flaskapp-6c4fccdf99-zp8mk   1/1       Running   0          3m        10.1.0.24   docker-for-desktop
nginx-85fb469b96-lr982      1/1       Running   0          1h        10.1.0.19   docker-for-desktop
redis-5b44bb8d97-wwmll      1/1       Running   0          1h        10.1.0.22   docker-for-desktop
复制代码

多次访问服务:

➜  docker2istio curl http://127.0.0.1:30457
Hello World by 10.1.0.21 from 192.168.65.3 ! 该页面已被访问 2 次。
➜  docker2istio curl http://127.0.0.1:30457
Hello World by 10.1.0.23 from 192.168.65.3 ! 该页面已被访问 3 次。
➜  docker2istio curl http://127.0.0.1:30457
Hello World by 10.1.0.24 from 192.168.65.3 ! 该页面已被访问 4 次。
➜  docker2istio curl http://127.0.0.1:30457
复制代码

结合前面看到的flaskapp的IP,可以比较清晰的看到请求会自动负载到不同的Pod。

清理

k8s下的容器清理也非常简单, 使用 kubectl delete -f k8s :

service "flaskapp" deleted
deployment.extensions "flaskapp" deleted
configmap "nginx-config" deleted
service "nginx" deleted
deployment.extensions "nginx" deleted
service "redis" deleted
deployment.extensions "redis" deleted
复制代码

容器编排

实际上,k8s集群在多集群情况下,会自动将Pod调度到合适的节点,这就是容器编排的概念。这种能力,主要有2个方式。

节点标签

我们的k8s演示集群节点情况如下:

[tyhall51@192-168-10-21 k8s]$ kubectl get nodes
NAME            STATUS   ROLES    AGE    VERSION
192-168-10-14   Ready    <none>   13d    v1.14.0
192-168-10-18   Ready    <none>   130d   v1.14.0
192-168-10-21   Ready    master   131d   v1.14.0
复制代码

部署示例应用到k8s演示集群:

[tyhall51@192-168-10-21 docker2istio]$ kubectl apply -f k8s -n docker2istio
service/flaskapp created
deployment.extensions/flaskapp created
configmap/nginx-config created
service/nginx created
deployment.extensions/nginx created
service/redis created
deployment.extensions/redis created
复制代码

!!!注意 为了不和别的服务发生名称冲突,这里部署时候使用了 -n docker2istio 参数,创建了一个独立的名称空间。名称空间可以使用 kubectl create namespace docker2istio 命令创建。

查看名称空间下的服务:

[tyhall51@192-168-10-21 docker2istio]$ kubectl get service -n docker2istio
NAME       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
flaskapp   ClusterIP   10.101.127.107   <none>        5000/TCP       47s
nginx      NodePort    10.103.147.187   <none>        80:30387/TCP   46s
redis      ClusterIP   10.106.162.13    <none>        6379/TCP       46s
复制代码

查看名称空间下的pod:

[tyhall51@192-168-10-21 docker2istio]$ kubectl get pods -o wide -n docker2istio
NAME                        READY   STATUS    RESTARTS   AGE   IP             NODE            NOMINATED NODE   READINESS GATES
flaskapp-589c4cdf86-sftr9   1/1     Running   0          81s   10.244.2.30    192-168-10-14   <none>           <none>
nginx-55b87f44ff-b4x88      1/1     Running   0          81s   10.244.2.31    192-168-10-14   <none>           <none>
redis-7fc7fc64fb-2nzjq      1/1     Running   0          81s   10.244.1.195   192-168-10-18   <none>           <none>
复制代码

参考前文,修改副本数量参数 replicas ,对flaskapp进行扩容:

[tyhall51@192-168-10-21 docker2istio]$ kubectl get pods -o wide -n docker2istio
NAME                        READY   STATUS    RESTARTS   AGE     IP             NODE            NOMINATED NODE   READINESS GATES
flaskapp-589c4cdf86-8jzwx   1/1     Running   0          4s      10.244.1.197   192-168-10-18   <none>           <none>
flaskapp-589c4cdf86-sftr9   1/1     Running   0          3m10s   10.244.2.30    192-168-10-14   <none>           <none>
flaskapp-589c4cdf86-tz98x   1/1     Running   0          4s      10.244.1.196   192-168-10-18   <none>           <none>
nginx-55b87f44ff-b4x88      1/1     Running   0          3m10s   10.244.2.31    192-168-10-14   <none>           <none>
redis-7fc7fc64fb-2nzjq      1/1     Running   0          3m10s   10.244.1.195   192-168-10-18   <none>           <none>
复制代码

这里就可以看到,扩容完成后,flaskapp的3个pod会自动调度到 192-168-10-18192-168-10-18 2个业务节点。

192-168-10-14节点的磁盘使用的是高速ssd,io性能会更好一些,我们希望 redis 能够调度到该节点。

首先,给192-168-10-14节点打上 storage=ssd 的标签:

[tyhall51@192-168-10-21 docker2istio]$ kubectl label nodes 192-168-10-14 storage=ssd
node/192-168-10-14 labeled
复制代码

检查标签是否正常标记:

[tyhall51@192-168-10-21 docker2istio]$ kubectl get nodes --show-labels | grep ssd
192-168-10-14   Ready    <none>   13d    v1.14.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=192-168-10-14,kubernetes.io/os=linux,storage=ssd
复制代码

然后修改 k8s/redis.yaml ,增加 nodeSelector 数值,其值为 storage: ssd , 修改完成的deployment如下:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: redis
spec:
  replicas: 1
  template:
    metadata:
      labels:
        name: redis
    spec:
      containers:
      - image: redis:4-alpine3.8
        name: redis
        ports:
        - containerPort: 6379
      nodeSelector:
        storage: ssd
复制代码

使用 kubectl apply -f k8s/redis.yaml -n docker2istio 应用修改。查看docker2istio的pod分布情况:

[tyhall51@192-168-10-21 docker2istio]$ kubectl get pods -o wide -n docker2istio
NAME                        READY   STATUS    RESTARTS   AGE   IP             NODE            NOMINATED NODE   READINESS GATES
flaskapp-589c4cdf86-8jzwx   1/1     Running   0          11m   10.244.1.197   192-168-10-18   <none>           <none>
flaskapp-589c4cdf86-sftr9   1/1     Running   0          14m   10.244.2.30    192-168-10-14   <none>           <none>
flaskapp-589c4cdf86-tz98x   1/1     Running   0          11m   10.244.1.196   192-168-10-18   <none>           <none>
nginx-55b87f44ff-b4x88      1/1     Running   0          14m   10.244.2.31    192-168-10-14   <none>           <none>
redis-66f66896b6-7666t      1/1     Running   0          4s    10.244.2.35    192-168-10-14   <none>           <none>
复制代码

可见redis节点重新被调度到192-168-10-14节点,表现出了节点标签的亲和力。

节点污点

在k8s演示集群中192-168-10-21是master节点,默认不会调度业务pod,这种能力是采用节点污点实现的。 取消192-168-10-21调度污点:

kubectl taint node 192-168-10-21 node-role.kubernetes.io/master:NoSchedule-
复制代码

然后扩容flaskapp的副本数到6个,观察pod分布情况:

[tyhall51@192-168-10-21 docker2istio]$ kubectl get pods -o wide -n docker2istio
NAME                        READY   STATUS         RESTARTS   AGE     IP             NODE            NOMINATED NODE   READINESS GATES
flaskapp-589c4cdf86-8jzwx   1/1     Running        0          20m     10.244.1.197   192-168-10-18   <none>           <none>
flaskapp-589c4cdf86-92rm5   1/1     Running        0          5s      10.244.2.36    192-168-10-14   <none>           <none>
flaskapp-589c4cdf86-bfhs8   1/1     Running        0          5s      10.244.0.26    192-168-10-21   <none>           <none>
flaskapp-589c4cdf86-sftr9   1/1     Running        0          23m     10.244.2.30    192-168-10-14   <none>           <none>
flaskapp-589c4cdf86-srv25   1/1     Running        0          5s      10.244.0.25    192-168-10-21   <none>           <none>
flaskapp-589c4cdf86-tz98x   1/1     Running        0          20m     10.244.1.196   192-168-10-18   <none>           <none>
nginx-55b87f44ff-b4x88      1/1     Running        0          23m     10.244.2.31    192-168-10-14   <none>           <none>
redis-66f66896b6-7666t      1/1     Running        0          9m30s   10.244.2.35    192-168-10-14   <none>           <none>
复制代码

这里可以看到,有2个pod被调到到192-168-10-21节点了。

重新设置污点:

[tyhall51@192-168-10-21 docker2istio]$ kubectl taint node 192-168-10-21 node-role.kubernetes.io/master=:NoSchedule
node/192-168-10-21 tainted
复制代码

删除在192-168-10-21上的2个pod:

kubectl delete pod/flaskapp-589c4cdf86-bfhs8 -n docker2istio
kubectl delete pod/flaskapp-589c4cdf86-srv25 -n docker2istio
复制代码

观察pod分布情况:

[tyhall51@192-168-10-21 docker2istio]$ kubectl get pods -o wide -n docker2istio
NAME                        READY   STATUS    RESTARTS   AGE     IP             NODE            NOMINATED NODE   READINESS GATES
flaskapp-589c4cdf86-8jzwx   1/1     Running   0          25m     10.244.1.197   192-168-10-18   <none>           <none>
flaskapp-589c4cdf86-92rm5   1/1     Running   0          4m40s   10.244.2.36    192-168-10-14   <none>           <none>
flaskapp-589c4cdf86-fp5w4   1/1     Running   0          73s     10.244.2.37    192-168-10-14   <none>           <none>
flaskapp-589c4cdf86-lv2ch   1/1     Running   0          73s     10.244.1.199   192-168-10-18   <none>           <none>
flaskapp-589c4cdf86-p9kb6   1/1     Running   0          7s      10.244.2.38    192-168-10-14   <none>           <none>
flaskapp-589c4cdf86-sftr9   1/1     Running   0          28m     10.244.2.30    192-168-10-14   <none>           <none>
nginx-55b87f44ff-b4x88      1/1     Running   0          28m     10.244.2.31    192-168-10-14   <none>           <none>
redis-66f66896b6-7666t      1/1     Running   0          14m     10.244.2.35    192-168-10-14   <none>           <none>
复制代码

可以看到删除后的pod,在192-168-10-18和192-168-10-14这2个业务节点上重建了。

总结

k8s相对于compose:

  1. 管理规模扩大,由单机到集群。
  2. 扩容更方便了,可以无缝扩容。
  3. 部署策略更完善,可以对容器进行 编排

相关组件

  1. Etcd

etcd 是一个分布式键值对存储,设计用来可靠而快速的保存关键数据并提供访问。通过分布式锁,leader选举和写屏障(write barriers)来实现可靠的分布式协作。etcd集群是为高可用,持久性数据存储和检索而准备。k8s中使用etcd作为集群信息存储。

  1. Efk

EFK (Elasticsearch + Fluentd + Kibana) 是kubernetes官方推荐的日志收集方案

  1. helm
Helm helps you manage Kubernetes applications — Helm Charts help you define, install, and upgrade even the most complex Kubernetes application.
  1. Rock
File, Block, and Object Storage Services for your Cloud-Native Environments

...

...


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Pro JavaScript Techniques

Pro JavaScript Techniques

John Resig / Apress / 2006-12-13 / USD 44.99

Pro JavaScript Techniques is the ultimate JavaScript book for the modern web developer. It provides everything you need to know about modern JavaScript, and shows what JavaScript can do for your web s......一起来看看 《Pro JavaScript Techniques》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

SHA 加密
SHA 加密

SHA 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具