前一篇啊,我们学完了基本的配置。这一篇,我们来看下服务部署的配置。我们先来看张图,理解下k8s的应用场景和调用流程:
看上图,首先,master是控制节点,负责编排、管理、调度用户提交的作业。kube-apiserver负责api服务,它会处理集群的持久化数据并保存在etcd
中、kube-scheduler负责调度、kube-controller-manager负责容器编排。
node是计算节点,CRI(Container Runtime Interface)的远程调用接口,这个接口定义了容器运行时的各项核心操作。OCI(Open Container Initiative) 容器运行时通过OCI同底层的Linux操作系统进行交互。设备插件是用来管理宿主机物理设备的组件。gRPC是可以在任何环境中运行的现代开源高性能 RPC 框架。RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。
我们再来看张图,是我们开发时需要用到的架构图,很有用:
Pod 是 K8S 中最小的可调度单元(可操作/可部署单元),它里面可以包含1个或者多个 Docker 容器,在 Pod 内的所有 Docker 容器,都会共享同一个网络、存储卷、端口映射规则,一个 Pod 拥有一个 IP,但这个 IP 会随着Pod的重启,创建,删除等跟着改变,所以不固定且不完全可靠,这也就是 Pod 的 IP 漂移问题。这个问题我们可以使用下面的 Service 去自动映射,Pod 是一个容器组,里面有很多容器,容器组内共享资源。
希望批量启动和管理多个Pod实例,就可以使用deployment。有了Pod实例后就需要以固定的IP地址以负载均衡的方式访问多个Pod实例,就有了Service。
下面我们就来看下如何部署:
我们现需要编写一个配置文件:
mkdir deployment && cd deployment vim deployment-user-v1.yaml
文件的内容如下:
apiVersion: apps/v1 #API 配置版本 kind: Deployment #资源类型 metadata: name: user-v1 #资源名称 spec: selector: matchLabels: app: user-v1 #告诉deployment根据规则匹配相应的Pod进行控制和管理,matchLabels字段匹配Pod的label值 replicas: 3 #声明一个 Pod,副本的数量 template: metadata: labels: app: user-v1 #Pod的名称 spec: #组内创建的 Pod 信息 containers: - name: nginx #容器的名称 image: registry.cn-beijing.aliyuncs.com/zhangrenyang/nginx:user-v1 #使用哪个镜像 ports: - containerPort: 80 #容器内映射的端口
然后执行:
kubectl apply -f deployment-user-v1.yaml
deployment.apps/user-v1 created
然后我们查看下状态:
kubectl get pod
其中:
- name 是 Pod的名称
- READY 为容器状态,格式为可用容器/所有容器数量
- STATUS 为 Pod 的运行状态
- RESTARTS 为重启数量
- AGE 为 Pod 运行时间
Pod部署完了,下面我们需要部署下Services:
deployment 是无状态的,deployment 并不会对 pod 进行网络通信和分发,Pod 的 IP 在运行时还会经常进行漂移且不固定,想访问服务需要使用 Service 组织统一的 Pod 访问入口,可以定义Service 来进行统一组织 Pod 服务访问,负责自动调度和组织deployment中 Pod 的服务访问,由于自动映射 Pod 的IP,同时也解决了 Pod 的IP漂移问题。
我们同样创建一个user-service-v1.yaml并编辑内容:
apiVersion: v1 kind: Service metadata: name: service-user-v1 spec: selector: app: user-v1 ports: - protocol: TCP port: 80 targetPort: 80 type: NodePort
启动它:
kubectl apply -f user-service-v1.yaml
service/service-user-v1 created
查看状态:
kubectl get svc
然后,我们可以在任何节点上访问:
curl http://172.31.178.169:30859 curl http://172.31.178.170:30859
我们可能会根据请求路径前缀的匹配,权重,甚至根据 cookie/header
的值去访问不同的服务,为了达到这种负载均衡的效果,我们可以使用kubernetes的另一个组件ingress,
ingress-nginx 是基于 nginx 的一个 ingress 实现。可以实现正则匹配路径,流量转发,基于 cookie header 切分流量(灰度发布)。
#wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/baremetal/deploy.yaml wget https://img.zhufengpeixun.com/deploy.yaml
编辑vi deploy.yaml d$:
namespace: ingress-nginx spec: type: NodePort ports: - name: http port: 80 protocol: TCP targetPort: http + nodePort: 31234 - name: https port: 443 protocol: TCP targetPort: https + nodePort: 31235 + image: registry.cn-hangzhou.aliyuncs.com/bin_x/nginx-ingress:v0.34.1@sha256:80359bdf124d49264fabf136d2aecadac729b54f16618162194356d3c78ce2fe
拉取镜像并自动部署:
kubectl apply -f deploy.yaml
查看pods部署状态:
kubectl -n ingress-nginx get svc
下面我们编辑下vi ingress.yaml文件,ingress 服务的配置也是使用 yaml 文件进行管理。annotations 是 ingress 的主要配置项目,可以用来修改这些配置来修改 ingress 的行为。我们可以通过修改这些配置来实现灰度发布,跨域资源,甚至将 www.abc.com 重定向到 abc.com。rules 是 ingress 配置路径转发规则的地方,当我们去访问 /front 时, ingress 就会帮我们调度到 front-service-v1 这个 service 上面。path 可以是一个路径字符串,也可以是一个正则表达式。backend 则是 k8s 的 service 服务, serviceName 是服务名称, servicePort 是服务端口。backend 可以用来给 ingress 设置默认访问的 Service 服务。当请求不匹配 rules 中任何一条规则时,则会去走 backend 中的配置。
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: nginx-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / kubernetes.io/ingress.class: nginx spec: rules: - http: paths: - path: /user backend: serviceName: user-service-v1 servicePort: 80 - path: /pay backend: serviceName: pay-service-v1 servicePort: 80 backend: serviceName: user-service-v1 servicePort: 80
启动:
kubectl apply -f ./ingress.yaml
测试:
curl http://172.16.244.93:31234/user curl http://172.16.244.94:31234/user curl http://172.16.244.93:31234/pay curl http://172.16.244.94:31234/pay
查看:
kubectl describe ingress
到此,我们的部署基本上就ok了。下面再继续学习后面的内容。
站在巨人的肩膀上,希望我可以看的更远。