K8S简介

k8s架构图

 

K8S的优势

1、自动装箱:基于容器对应用运行环境的资源配置要求自动部署应用容器

2、故障迁移(自愈):当某一个node节点关机或挂掉后,node节点上的服务会自动转移到另一个node节点上,这个过程所有服务不中断。这是docker或普通云主机是不能做到的

3、资源调度(弹性伸缩):当node节点上的cpu、内存不够用的时候,可以扩充node节点,新建的pod就会被kube-schedule调度到新扩充的node节点上,如果CPU负载低于阈值则减少容器的数量

4、服务的自动发现和负载均衡: 用户不需使用额外的服务发现机制,就能够基于 Kubernetes 自身能力实现服务发现和 负载均衡。

5、资源隔离:创建开发、运维、测试三个命名空间,切换上下文后,开发人员就只能看到开发命名空间的所有pod,看不到运维命名空间的pod,这样就不会造成影响,互不干扰

6、安全:不同角色有不同的权限,查看pod、删除pod等操作;RBAC认证增加了k8s的安全

7、滚动升级和一键回滚: Kubernetes 逐渐部署对应用程序或其配置的更改,同时监视应用程序运行状况,以确保它不会同时终止所有实例。如果出现问题,Kubernetes会为您恢复更改

8. 密钥和配置管理:在不需要重新构建镜像的情况下,可以部署和更新密钥和应用配置,类似热部署。

9. 存储编排:自动实现存储系统挂载及应用,特别对有状态应用实现数据持久化非常重要 存储系统可以来自于本地目录、网络存储(NFS、Gluster、Ceph 等)、公共云存储服务

 

K8s好用在什么地方?

 

k8s重要概念介绍#

 
 
组件名称作用
Cluster 资源的集合。我们的k8s利⽤这些资源运⾏各种基于容器的应用。是计算、存储和网络资源的集合
Master Cluster的⼤脑。司令部。主要的任务就是用来调度的。决定我们的应用应该放到哪⾥去执行。
为了高可⽤,也可以运⾏多个master。职责是运行容器应用。
Node 来负责运⾏容器应⽤。Node是由Master去管理的,负责监控和容器状态的汇报。
Pod k8s的最小工作单元,包含1orN个容器。
Pod的使用方式:
⼀个pod运⾏⼀个容器
最常⽤的就是这种情况。
⼀个pod运⾏多个容器
⼀定是非常紧密相关的⼀组容器,并且需要资源的共享。⼀起启动、⼀起停止。
Controller k8s通过它来管理Pod
包含:Deployment、ReplicaSet、DaemonSet、StatefulSet、Job。
Deployment
就是我们最常⽤的Controller。它可以管理Pod的多个副本。(即:--replicas=3),并且可以确保Pod按照期望的状态去运⾏。
ReplicaSet
它也是管理Pod的多个副本。
我们使⽤deployment的时候,会⾃动的创建ReplicaSet,最终是有ReplicaSet去创建的pod,而我们并不是去直接的使⽤它。
DaemonSet
⽤于每个Node最多只运⾏⼀个Pod副本的创建。
StatefulSet
保证副本按照固定的顺序启动、更新、删除。
Service

为Pod提供了负载均衡、固定的IP和Port
多个相同的pod组成一个服务,统一对外提供服务;pod是不稳定的,ip会变化的。所以我们需要⼀个固定的ip或port。

区别:
Controller ——> 负责k8s运行容器的。
Service ——> 负责k8s访问容器的。

Namespace 解决同一个Cluster中,如何区别分开Controller、Pod等资源的问题,资源隔离!
  • Volume: 存储卷,pod对外暴露的共享目录,它可以挂载在宿主机上,这样就能让同node上多个pod共享一个目录。
  • Replication Controller: 用于控制pod集群的控制器,可以制定各种规则来让它控制一个service中的多个pod的创建和消亡, 很多地方简称为rc。
  • Namespace: 命名空间,用于将一个k8s集群隔离成不同的空间,pod, service, rc, volume 都可以在创建的时候指定其namespace。
  • StatefulSet: 有状态集群,比如一个主从的mysql集群就是有状态集群,需要先启动主再启动从,这就是一种有状态的集群。
  • Persistent Volume: 持久存储卷。之前说的volume是挂载在一个pod上的,多个pod(非同node)要共享一个网络存储,就需要使用持久存储卷,简称为pv。
  • Persistent Volume Claim: 持久存储卷声明。他是为了声明pv而存在的,一个持久存储,先申请空间,再申明,才能给pod挂载volume,简称为pvc。
  • Label: 标签。我们可以给大部分对象概念打上标签,然后可以通过selector进行集群内标签选择对象概念,并进行后续操作。
  • Secret: 私密凭证。密码保存在pod中其实是不利于分发的。k8s支持我们创建secret对象,并将这个对象打到pod的volume中,pod中的服务就以文件访问的形式获取密钥。
  • EndPoint: 用于记录 service 和 pod 访问地址的对应关系。只有 service 配置了 selector, endpoint controller 才会自动创建endpoint对象。

如果不理解没啥关系,看一遍有印象下,下面我们一个个琢磨琢磨。

master

k8s的master节点上有三个进程,它们都是以docker的形式存在的。我们在k8s的master节点看docker ps 就可以看到这几个进程:

8824aad1ee95        e851a7aeb6e8                     "kube-apiserver --ad…"   3 days ago          Up 3 days                               k8s_kube-apiserver_kube-apiserver-docker-for-desktop_kube-system_f23c0965aad6df9f61b1c9c4bb953cf5_0
a9ce81ec9454        978cfa2028bf                     "kube-controller-man…"   3 days ago          Up 3 days                               k8s_kube-controller-manager_kube-controller-manager-docker-for-desktop_kube-system_1dc44822f21a9cbd68cc62b1a4684801_0
85da3f6e700f        d2c751d562c6                     "kube-scheduler --ad…"   3 days ago          Up 3 days                               k8s_kube-scheduler_kube-scheduler-docker-for-desktop_kube-system_b6155a27330304c86badfef38a6b483b_0

其中的 apiserver 是提供 k8s 的 rest api 服务的进程。当然它也包括了 restapi 的权限认证机制。 k8s 的 apiserver 提供了三种权限认证机制:

  • https
  • http + token
  • http + base(username + password)

我们也可以通过使用kubectl proxy 在 master 上来创建一个代理,从而外部可以访问这个 k8s 集群。

kube-controller-manager 是用来管理所有的 controller 的。之前我们说的 Replication Controller 就是一种管控 Pod 副本的Controller, 其他相关的 Controller 还有:

  • Replication Controller
  • Node Controller: 实时获取Node的相关信息,实现管理和监控集群中的各个Node节点的相关控制功能
  • ResourceQuota Controller: 确保指定的资源对象在任何时候都不会超量占用系统物理资源
  • NameSpace Controller: 定时通过API Server读取这些Namespace信息
  • ServiceAccount Controller: 监听Service变化,如果是一个LoadBalancer类型的Service,则确保外部的云平台上对该Service对应的LoadBalancer实例被相应地创建、删除及更新路由转发表
  • Token Controller
  • Service Controller
  • EndPoint Controller : Service 和选择 Pod 的对应关系。

kube-scheduler 负责 Pod 调度,接收 Controller Manager 创建的新的Pod,为其选择一个合适的Node,并且在Node上创建Pod。

一个k8s集群只有一个master节点,所以 master 节点的高可用性是一个问题,一旦 master 节点挂了,整个集群也就挂了。这点真有点神奇。所以网上关于搭建高可用的k8s Master 节点的方案有很多:

https://jishu.io/kubernetes/kubernetes-master-ha/
https://blog.51cto.com/ylw6006/2164981
https://jimmysong.io/kubernetes-handbook/practice/master-ha.html

Node

Node 是 k8s 的工作节点,Node 一般是一个虚拟机或者物理机,每个 node 上都运行三个服务:

  • docker
  • kubelet
  • kube-proxy

     

docker 就是 docker server,它提供

kubelet 是一个管理系统,它管理本个node上的容器的生命周期,定期从kube-apiserver组件接收新的或修改的Pod规范,并确保Pod及其容器在期望规范下运行。同时该组件作为工作节点的监控组件,向kube-apiserver汇报主机的运行状况。

kube-proxy 是管理 service 的访问入口,包括集群内 pod 到 service 的访问,以及集群外访问service。

可用性

其实k8s自身的可用性是比较弱的,如果master挂了,那么master上的三个服务也就挂了。node挂了,如果node上的pod是被 controller控制住的话,controller会在其他node上启动对应的pod。

 

K8S部署实战

//pod是最小调度单元,包含了一个业务功能
[root@localhost ~]# kubectl get pods -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS        AGE
//收集主机信息并发送给指定check服务器
default       netchecker-agent-n4zvc                     1/1     Running   0               5m22s
default       netchecker-server-589d76f698-wh8jr         2/2     Running   1 (5m14s ago)   5m20s
//一套开源的网络和网络安全方案
kube-system   calico-kube-controllers-75fcdd655b-8khd4   1/1     Running   0               5m36s
kube-system   calico-node-mpppj                          1/1     Running   0               5m52s
//作为内网的DNS服务器,用于服务发现
kube-system   coredns-76b4fb4578-dsj8r                   1/1     Running   0               5m29s
kube-system   dns-autoscaler-7874cf6bcf-44clw            1/1     Running   0               5m27s
//api
kube-system   kube-apiserver-master                      1/1     Running   0               6m51s
//通过 apiserver 监控整个集群的状态,并确保集群处于预期的工作状态
kube-system   kube-controller-manager-master             1/1     Running   1               6m51s
//实现Kubernetes Service的通信与负载均衡机制
kube-system   kube-proxy-488bp                           1/1     Running   0               6m4s
//控制面进程,负责将 Pods 指派到节点上
kube-system   kube-scheduler-master                      1/1     Running   1               6m56s
//监控kubernetes集群资源
kube-system   metrics-server-749474f899-8bbrf            1/1     Running   0               5m15s
kube-system   nginx-proxy-worker                         1/1     Running   0               6m4s
//大幅提升集群内DNS解析性能
kube-system   nodelocaldns-b5vgs                         1/1     Running   0               5m26s
//deployment通过yaml定义了一组pod,动态管理和伸缩
[root@master ~]# kubectl get deploy -A
NAMESPACE     NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
default       netchecker-server         1/1     1            1           2d12h
kube-system   calico-kube-controllers   1/1     1            1           2d12h
kube-system   coredns                   1/1     1            1           2d12h
kube-system   dns-autoscaler            1/1     1            1           2d12h
kube-system   metrics-server            1/1     1            1           2d12h
[root@master ~]# kubectl get -o yaml deploy netchecker-server

创建一个门户网站

之前提到的k8s是通过yaml文件定义deployment,然后再启动服务暴露端口号给用户访问,那么我们先定义一个最简单的yaml文件myTestWeb.yaml:

//myTestWeb.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: mytestweb
  name: mytestweb
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mytestweb
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: mytestweb
    spec:
      containers:
      - image: nginx:latest
        name: nginx
        resources: {}
status: {}

[root@master k8s_test]# kubectl apply -f myTestWeb.yaml
[root@master k8s_test]# kubectl get deployments
NAME                READY   UP-TO-DATE   AVAILABLE   AGE
mytestweb           1/1     1            1           79s
netchecker-server   1/1     1            1           2d16h
[root@master k8s_test]# kubectl get pods
NAME                                 READY   STATUS    RESTARTS        AGE
mytestweb-575f89bf65-ms4cg           1/1     Running   0               87s

//service.yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: mytestweb
  name: mytestweb
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 80
  selector:
    app: mytestweb
  type: NodePort
status:
  loadBalancer: {}

service/mytestweb created
[root@master k8s_test]# kubectl get service
NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes           ClusterIP   10.233.0.1       <none>        443/TCP          2d19h
mytestweb            NodePort    10.233.159.30    <none>        8080:32046/TCP   19s

//修改一下门户网站页面

这样我们访问192.168.206.131:32046就可以访问了:

高可用水平扩容

如果我们发现访问我们的门户网站流量很大,这时我们可以生成5个web服务器网站,然后用作高可用以及负载均衡,具体做法只要修改myTestWeb.yaml中的replicas: 1声明成replicas: 10,最后再apply一下即可:

[root@master k8s_test]# kubectl get pod
NAME                                 READY   STATUS    RESTARTS     AGE
mytestweb-575f89bf65-8zgrr           1/1     Running   0            13m
mytestweb-575f89bf65-cplr8           1/1     Running   0            13m
mytestweb-575f89bf65-ms4cg           1/1     Running   0            4h48m
mytestweb-575f89bf65-pwzl5           1/1     Running   0            13m
mytestweb-575f89bf65-vng4n           1/1     Running   0            13m

[root@master k8s_test]# kubectl describe service/mytestweb
Name:                     mytestweb
Namespace:                default
Labels:                   app=mytestweb
Annotations:              <none>
Selector:                 app=mytestweb
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.233.159.30
IPs:                      10.233.159.30
Port:                     <unset>  8080/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  32046/TCP
Endpoints:                10.234.218.10:80,10.234.218.9:80,10.234.28.6:80 + 2 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

//循环访问
[root@master k8s_test]# while true;do curl 192.168.206.131:32046;sleep 1;done
//查看各pod运行日志发现,确实实现了负载均衡
192.168.206.131 - - [04/Apr/2022:11:57:10 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"
192.168.206.131 - - [04/Apr/2022:11:57:11 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"
10.234.218.0 - - [04/Apr/2022:11:57:09 +0000] "GET / HTTP/1.1" 200 330 "-" "curl/7.29.0" "-"
10.234.218.0 - - [04/Apr/2022:11:57:08 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"
10.234.218.0 - - [04/Apr/2022:11:57:07 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"

//service的node调度策略是可以修改的
/*
Taint 污点:节点不做普通分配调度,是节点属性,属性值有三个
NoSchedule:一定不被调度
PreferNoSchedule:尽量不被调度(也有被调度的几率)
NoExecute:不会调度,并且还会驱逐Node已有Pod

调度器标签选择也会影响调度,例如yaml文件说增加如下,那么只有打上键值对mylabel=pickup的node才有pod会调度在上面:
nodeSelector:
        mylabel: pickup
*/

默认配置下,Scheduler会将Pod调度到所有可用的Node。不过有些情况我们可以通过lable将Pod部署到指定的Node,比如将有大量磁盘I/O的Pod部署到配置了SSD的 Node;或者Pod需要GPU,需要运行在配置了GPU的节点上。

  • 给k8s-node1添加标签——disktype=ssd
kubectl label node k8s-node1 disktype=ssd 
  • 修改myTestWeb.yaml配置文件,指定nodeSelector为上一步新建的label。
nodeSelector: 
 disktype: ssd 
  • 重新部署Deployment
kubectl apply -f myTestWeb.yaml
//缩容就不写了,数字减回去,然后apply

删除deployment

假设现在配置的是2个pod数。那么如果我们只是删除其中的一个pod,依然会被deployment根据配置,再补充为2个pod。

  • 当我们删除掉deployment的时候,pod也会随之自动被删除。

    • 删除pod

      kubectl delete pod mytestweb-7f4fc68488-5v4m7 
    • 删除deployment

      kubectl delete deployment mytestweb

有状态服务

之前的演示都是无状态的服务,即多个Pod创建是没有顺序的,且共享存储。而有状态的服务具有固定的主机名具以及有持久化存储。

k8s支持存储相关的是PV和PVC,这个在之前的章节介绍过,这里只讲创建关系,pv是显示地指示提供存储的大小和位置,而PVC是一个pv抽象,也是说我们绑定一个pvc后,它会按照storageClassName、accessModes 以及容量这些是否满足要求,遍历各个PV,并将满足要求的绑定起来,这有一个好处就是假如某一个PV失效了,我们可以新建一个满足PVC模板的PV即可,否则没有PVC,那么我们就需要修改各个依赖该失效PV的pod的yaml文件,改成新的PV,如果pod数量很多,那改起来就像自行车爆胎 -气炸了。

我们来看看几种PV存储的类型,其实就是yaml定义,用的时候就是apply一下就行,很方便:

/*
ReadWriteOnce:可读科写,但支持被单个node挂载
ReadOnlyMany:可以以读的方式被多个node挂载
ReadWriteMany:可以以读写的方式被多个node挂载
*/

//本地存储
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv1
  labels:
    type: local
spec:
  storageClassName: manual #声明类型后续PVC会匹配绑定
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  hostPath:                #声明本地存储
    path: /data/hostpath

//类似nfs这种的远端存储,阿里云,AWS
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv2
  labels:
    type: remote
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  nfs: 
    path: /data/nfs  # 声明nfs存储
    server: 192.168.108.100

//声明PVC统一管控内存,需求2G,acess权限为RWM,类型为manual,那么my-pv1和my-pv2就会被bound
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  storageClassName: manual
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 2Gi


[root@master k8s_test]# kubectl get pv,pvc
NAME                     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 
persistentvolume/my-pv   1Gi        RWX            Retain           Bound    default/my-pvc

NAME                           STATUS   VOLUME   CAPACITY   ACCESS MODES
persistentvolumeclaim/my-pvc   Bound    my-pv    1Gi        RWX        

滚动发布与回退

由于k8s yaml定义一切的特性,我们发布新版本也可以做到热升级,只需要将指定我们想要发布的新版本docker镜像,然后apply一下yaml即可:

spec:                  
      containers:
      - image: nginx:1.15 # 指定镜像版本为1.15
        name: nginx

# 查看升级版本
[root@master k8s_test]# kubectl rollout status deploy mytestweb
deployment "web" successfully rolled out

# 查看历史版本
[root@master k8s_test]# kubectl rollout history deployment mytestweb
deployment.apps/mytestweb
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

#回滚到指定版本
kubectl rollout undo deploy mytestweb --to-revision=2

 

DaemonSet#

Deployment部署的副本pod会分布在各个Node上,每个Node都可能运行好几个副本。
Daemonsetl的不同之处在于:每个Node上最多只能运行一个副本。

Daemon Set的典型应用场景
1.在每个节点上运行存储 Daemon,比如 glusterd或 ceph
2.在每个节点上运行日志收集 Daemon,如 flunentdi或 logstashe
3.在毎个节点上运行监控 Daemon,比如 Prometheus Node Exporter或 collectd

查看k8s自己就用 Daemonsetie运行系统组件

Job#

容器按照持续运行时间,可以分为服务类容器和工作类容器。

  • 服务类容器通常持续提供服务,需 要一直运行,比如HTTP Server、Daemon等。
  • 工作类容器则是一次性任务,比如批处理程序,完成后容器就退出。

Kubernetes的Deployment、ReplicaSet和DaemonSet都用于管理服务类容器;

对于工作类容器,我们使用Job。

 

 k8s总结思考

 Master 节点结构如下:

  • apiserver 即 K8s 网关,所有的指令请求都必须要经过 apiserver ;
  • scheduler 调度器,使用调度算法,把请求资源调度到某一个 node 节点;
  • controller 控制器,维护 K8s 资源对象;
  • etcd 存储资源对象;

Node 节点

  • kubelet 在每一个 node 节点都存在一份,在 node 节点上的资源操作指令由 kubelet 来执行;
  • kube-proxy 代理服务,处理服务间负载均衡;
  • pod 是 k8s 管理的基本单元(最小单元), pod 内部是容器, k8s 不直接管理容器,而是管理 pod ;
  • docker 运行容器的基础环境,容器引擎;
  • fluentd 日志收集服务;

K8s 核心组件

1. K8s 组件

K8s 是用来管理容器,但是不直接操作容器,最小操作单元是 Pod (间接管理容器)

  • 一个 Master 有一群 Node 节点与之对应
  • Master 节点不存储容器,只负责调度、网管、控制器、资源对象存储
  • 容器的存储在 Node 节点,容器是存储在 Pod 内部的)
  • Pod 内部可以有一个容器,或者多个容器
  • Kubelet 负责本地 Pod 的维护
  • Kube-proxy 负责负载均衡,在多个 Pod 之间来做负载均衡

2. Pod 是什么?

  • pod 也是一个容器,这个容器中装的是 Docker 创建的容器, Pod 用来封装容器的一个容器, Pod 是一个虚拟化分组;
  • Pod 相当于独立主机,可以封装一个或者多个容器;

Pod 有自己的 IP 地址、主机名,相当于一台独立沙箱环境。

3. Pod 到底用来干什么?

通常情况下,在服务部署时候,使用 Pod 来管理一组相关的服务。一个 Pod 中要么部署一个服务,要么部署一组有关系的服务。

一组相关的服务是指:在链式调用的调用连路上的服务。

4. Web 服务集群如何实现?

实现服务集群:只需要复制多方 Pod 的副本即可,这也是 K8s 管理的先进之处, K8s 如果继续扩容,只需要控制 Pod 的数量即可,缩容道理类似。

5. Pod 底层网络,数据存储是如何进行的?

  • Pod 内部容器创建之前,必须先创建 Pause 容器;
  • 服务容器之间访问 localhost ,相当于访问本地服务一样,性能非常高;

6. ReplicaSet 副本控制器

控制 Pod 副本「服务集群」的数量,永远与预期设定的数量保持一致即可。当有 Pod 服务宕机时候,副本控制器将会立马重新创建一个新的 Pod ,永远保证副本为设置数量。

副本控制器:标签选择器-选择维护一组相关的服务(它自己的服务)

selector:
    app = web
    Release = stable
  • ReplicationController 副本控制器:单选
  • ReplicaSet 副本控制器:单选,复合选择

在新版的 K8s 中,建议使用 ReplicaSet 作为副本控制器, ReplicationController 不再使用了。

7. Deployment 部署对象

  • 服务部署结构模型
  • 滚动更新

ReplicaSet 副本控制器控制 Pod 副本的数量。但是,项目的需求在不断迭代、不断的更新,项目版本将会不停的的发版。版本的变化,如何做到服务更新?

部署模型:

  • ReplicaSet 不支持滚动更新, Deployment 对象支持滚动更新,通常和 ReplicaSet 一起使用;
  • Deployment 管理 ReplicaSet , RS 重新建立新的 RS ,创建新的 Pod ;

8. MySQL 使用容器化部署,存在什么样的问题?

  • 容器是生命周期的,一旦宕机,数据丢失
  • Pod 部署, Pod 有生命周期,数据丢失

对于 K8s 来说,不能使用 Deployment 部署 有状态 服务。

通常情况下, Deployment 被用来部署无状态服务,那么对于有状态服务的部署,使用 StatefulSet 进行有状态服务的部署。

什么是有状态服务?

  • 有实时的数据需要存储
  • 有状态服务集群中,把某一个服务抽离出去,一段时间后再加入机器网络,如果集群网络无法使用

什么是无状态服务?

  • 没有实时的数据需要存储
  • 无状态服务集群中,把某一个服务抽离出去,一段时间后再加入机器网络,对集群服务没有任何影响

9. StatefulSet
为了解决有状态服务使用容器化部署的一个问题。

  • 部署模型
  • 有状态服务

StatefulSet 保证 Pod 重新建立后, Hostname 不会发生变化, Pod 就可以通过 Hostname 来关联数据。

K8s 的服务注册与发现

1. Pod 的结构是怎样的?

  • Pod 相当于一个容器, Pod 有独立 IP 地址,也有自己的 Hostname ,利用 Namespace 进行资源隔离,独立沙箱环境。
  • Pod 内部封装的是容器,可以封装一个,或者多个容器(通常是一组相关的容器)

2. Pod 网络

  • Pod 有自己独立的 IP 地址
  • Pod 内部容器之间访问采用 Localhost 访问

Pod 内部容器访问是 Localhost,Pod 之间的通信属于远程访问。

3. Pod 是如何对外提供服务访问的?

Pod 是虚拟的资源对象(进程),没有对应实体(物理机,物理网卡)与之对应,无法直接对外提供服务访问。

那么该 如何解决这个问题 呢?

Pod 如果想要对外提供服务,必须绑定物理机端口。也就是说在物理机上开启端口,让这个端口和 Pod 的端口进行映射,这样就可以通过物理机进行数据包的转发。

概括来说:先通过物理机 IP + Port 进行访问,再进行数据包转发。

4.一组相关的 Pod 副本,如何实现访问负载均衡?

我们先明确一个概念, Pod 是一个进程,是有 生命周期 的。宕机、版本更新,都会创建新的 Pod 。这时候 IP 地址会发生变化, Hostname 会发生变化,使用 Nginx 做负载均衡就不太合适了。

所以我们需要依赖 Service 的能力。

5. Service 如何实现负载均衡?

简单来说, Service 资源对象包括如下三部分:

  • Pod IP : Pod 的 IP 地址
  • Node IP :物理机 IP 地址
  • Cluster IP :虚拟 IP ,是由 K8s 抽象出的 Service 对象,这个 Service 对象就是一个 VIP 的资源对象

6. Service VIP 更深入原理探讨

  • Service 和 Pod 都是一个进程, Service 也不能对外网提供服务;
  • Service 和 Pod 之间可以直接进行通信,它们的通信属于局域网通信;
  • 把请求交给 Service 后, Service 使用 iptable , ipvs 做数据包的分发;

7. Service 对象是如何和 Pod 进行关联的?

  • 不同的业务有不同的 Service ;
  • Service 和 Pod 通过标签选择器进行关联;
    selector:
        app=x 选择一组订单的服务 pod ,创建一个 service;
        通过 endpoints 存放一组 pod ip;
    

Service 通过标签选择器选择一组相关的副本,然后创建一个 Service 。

8. Pod 宕机、发布新的版本的时候, Service 如何发现 Pod 已经发生了变化?

每个 Pod 中都有 Kube-Proxy ,监听所有 Pod 。如果发现 Pod 有变化,就动态更新( etcd 中存储)对应的 IP 映射关系。

关键问题

1.企业使用 K8s 主要用来做什么?

  • 自动化运维平台

    创业型公司,中小型企业,使用 K8s 构建一套自动化运维平台,自动维护服务数量,保持服务永远和预期的数据保持一致性,让服务可以永远提供服务。这样最直接的好处就是降本增效。

  • 充分利用服务器资源

    互联网企业,有很多服务器资源「物理机」,为了充分利用服务器资源,使用 K8s 构建私有云环境,项目运行在云。 这在大型互联网公司尤为重要 。

  • 服务的无缝迁移

    项目开发中,产品需求不停的迭代,更新产品。这就意味着项目不停的发布新的版本,而 K8s 可以实现项目从开发到生产无缝迁移。

2. K8s 服务的负载均衡是如何实现的?

Pod 中的容器很可能因为各种原因发生故障而死掉。 Deployment 等 Controller 会通过动态创建和销毁 Pod 来保证应用整体的健壮性。换句话说, Pod 是脆弱的,但应用是健壮的。每个 Pod 都有自己的 IP 地址。当 controller 用新 Pod 替代发生故障的 Pod 时,新 Pod 会分配到新的 IP 地址。

这样就产生了一个问题:如果一组 Pod 对外提供服务(比如 HTTP ),它们的 IP 很有可能发生变化,那么客户端如何找到并访问这个服务呢?

K8s 给出的解决方案是 Service 。 Kubernetes Service 从逻辑上代表了一组 Pod ,具体是哪些 Pod 则是由 Label 来挑选。

Service 有自己 IP ,而且这个 IP 是不变的。客户端只需要访问 Service 的 IP , K8s 则负责建立和维护 Service 与 Pod 的映射关系。无论后端 Pod 如何变化,对客户端不会有任何影响,因为 Service 没有变。

3.无状态服务一般使用什么方式进行部署?

Deployment 为 Pod 和 ReplicaSet 提供了一个 声明式定义方法,通常被用来部署无状态服务。

Deployment 的主要作用:

定义 Deployment 来创建 Pod 和 ReplicaSet 滚动升级和回滚应用扩容和索容暂停和继续。 Deployment 不仅仅可以滚动更新,而且可以进行回滚,如果发现升级到 V2 版本后,服务不可用,可以迅速回滚到 V1 版本。

 

https://www.zhihu.com/question/279646705/answer/1592413564

posted @ 2014-12-20 10:27  南哥的天下  阅读(4556)  评论(0编辑  收藏  举报