kubernetes 组件

master

在这里插入图片描述

k8s的master,也称为控制平面,用于控制整个k8s集群的整体运作状态。控制平面的唯一入口为API Server,它监听6443,接入api server的唯一入口就是api server主机的6443端口,为https协议。

Api server 默认情况下,需要做用户认证,而非客户端直接请求即可,而是需要双向认证:发送自己的证书给客户端验证,也要求客户端提供客户端证书,并且是api server自身信任的CA颁发的证书,才是api server认可的证书。证书在部署时自动生成的,路径为/etc/kubernetes/pki/ca.crt

admin.conf文件就持有CA颁发的客户端证书,因此 需要admin.conf才可以接入api server。

Kubectl config view命令查看客户端证书:

ilinux@master:/etc/kubernetes$ kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://k8s-api.linux.io:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

此处显示的客户端证书,客户端私钥都会隐藏起来,但真正去连接时,都必须提供证书。

客户端通过向api server提交请求,以创建pod资源,由scheduler调度,由controller创建pod,这些pod是由控制器管理的pod。

也可以直接创建pod,称为自主式pod

用于控制pod的资源类型Deployment,需要赋值后才能创建具体的控制器,这也就是资源类型实例化为资源对象的过程。比如nginx-deploy -> nginx-pod。而此时需要访问pod时,必须借助李刚一个资源类型Service,创建特定的service实例nginx-svc,关联nginx-pod以调度用户请求。

node

在这里插入图片描述

数据平面,它负责两项工作:

(1) 运行pod

(2) 为pod设定service转换为当前节点的iptables/ipvs规则 ,依靠kube-proxy组件完成

kubernetes的基本操作

获取pod时,可以指定名称空间,它是名称空间级别的资源,默认为default。

  • 获取名称空间:
ilinux@master:~$ kubectl get ns
NAME              STATUS   AGE
default           Active   30d
kube-node-lease   Active   30d
kube-public       Active   30d
kube-system       Active   30d

  • 创建资源:kubectl create

    ilinux@master:~$ kubectl create namespace develop
    namespace/develop created
    
  • 删除资源:kubectl delete 资源类型 资源名 -n 名称空间

    ilinux@master:~$ kubectl delete ns/testing ns/develop
    namespace "testing" deleted
    namespace "develop" deleted
    

    可删除多个资源,删除名称空间很危险!

  • 查找资源

    ilinux@master:~$ kubectl get ns/default -o wide # 输出长格式
    NAME      STATUS   AGE
    default   Active   30d
    
    ilinux@master:~$ kubectl get ns/default -o yaml # 输出yaml格式
    apiVersion: v1
    kind: Namespace
    ...
    
    ilinux@master:~$ kubectl get ns/default -o json # 输出json格式
    {
        "apiVersion": "v1",
        "kind": "Namespace",
        ...
    }
    

    一般每个资源,都由5个一级字段,这是标准格式。这些字段往往都一样,分别为:apiVersion,Kind,metadata,spec,status

  • 输出描述信息,一般是当前状态信息

    ilinux@master:~$ kubectl describe ns/default
    Name:         default
    ...
    
  • 创建deployment控制器控制的pod

    ilinux@master:~$ kubectl create deploy nginx-dep --image=nginx:1.14-alpine
    deployment.apps/nginx-dep created
    

    此时创建了default名称空间的的nginx deploy控制器

  • 显示当前名称空间所有资源

    ilinux@master:~$ kubectl get all
    NAME                             READY   STATUS    RESTARTS   AGE
    pod/nginx-dep-6fcd89c765-hk5j5   1/1     Running   0          14s  # pod对象,由控制器创建
    
    NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   30d
    
    NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/nginx-dep   1/1     1            1           3m1s # deployment对象
    
    NAME                                   DESIRED   CURRENT   READY   AGE
    replicaset.apps/nginx-dep-6fcd89c765   1         1         1       14s # rs对象
    

    直接访问pod IP:

    ilinux@master:~$ kubectl get pods -o wide
    NAME                         READY   STATUS    RESTARTS   AGE     IP             NODE    NOMINATED NODE   READINESS GATES
    nginx-dep-6fcd89c765-hk5j5   1/1     Running   0          3m26s   10.244.2.163   node2   <none>           <none>
    ilinux@master:~$ curl 10.244.2.163
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
    
    
  • 删除pod

    ilinux@master:~$ kubectl delete pods/nginx-dep-6fcd89c765-hk5j5
    pod "nginx-dep-6fcd89c765-hk5j5" deleted
    

    删除后,控制器会自动重新创建一个pod

    此时客户端访问的pod IP,会变动。应该对用户透明,此时需要中间层:service

    客户端访问调度器,调度器把请求调度到后端。此时,调度器必须有IP+port,后端也需要IP+port。因此service必须明确指定IP+port。它实际创建了iptables规则,类似dnat规则:

    比如:DNAT -d 10.96.1.7 --dport 80 -j DNAT --to-destination 10.244.3.2:80

    Service就是生成此规则,每个节点上都会存在此规则。因此客户端访问时,请求会被自动拦截

  • 创建 service

    ilinux@master:~$ kubectl create service clusterip nginx-dep --tcp=80:80
    service/nginx-dep created
    ilinux@master:~$ kubectl describe svc/nginx-dep
    Name:              nginx-dep
    Namespace:         default
    Labels:            app=nginx-dep
    Annotations:       <none>
    Selector:          app=nginx-dep
    Type:              ClusterIP
    IP:                10.111.132.206
    Port:              80-80  80/TCP
    TargetPort:        80/TCP
    Endpoints:         10.244.2.164:80  # 关联的后端pod
    Session Affinity:  None
    Events:            <none>
    
    

    此时会自动关联,encpoints为后端port的地址,然后访问service IP即可访问到podIP

    此时删除pod,kubectl delete pods --all

    然后控制器重建,地址和调度主机可能都会变化。service关联的是新地址,因为所有变动会反应在api-server,它会通知一切的客户端并发生相应改变。

    Service地址如果变化了,客户端访问ip就出问题,因此可以使用service名称,比如curl nginx-dep,会提示解析失败。本地默认dns地址需要变化。必须让coreDNS的解析,因此kubectl get svc -n kube-system,获取它的dns地址,然后临时把nameserver修改为coreDNS IP

    ilinux@master:~$ kubectl get pods -n kube-system -o wide
    NAME                             READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
    coredns-7ff77c879f-lxrhv         1/1     Running   37         30d   10.244.0.76    master   <none>           <none>
    ...
    
    root@master:~# cat /etc/resolv.conf 
    nameserver 10.244.0.76
    search default.svc.cluster.local
    
    ## 解析成功
    ilinux@master:~$ curl nginx-dep
    <!DOCTYPE html>
    <html>
    
    

    注意:搜索域默认为:default.svc.cluster.local. 它可再kubeadm init时,通过选项 --service-dns-domain指定,格式为 svc名称.namesapce.svc.默认域名cluster.local

    此时就算svc重建,也可通过名称访问成功。

deployment控制器可以按需伸缩pod的规模,看以下例子:

ilinux@master:~$ kubectl create deployment myapp --image=ikubernetes/myapp:v1
deployment.apps/myapp created

ilinux@master:~$ curl 10.244.2.166/hostname.html
myapp-5d587c4d45-8xzvt


ilinux@master:~$ kubectl create service clusterip myapp --tcp=80:80
service/myapp created

ilinux@master:~$ curl myapp
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

此时扩容:

ilinux@master:~$ kubectl scale --replicas=3 deployment/myapp
deployment.apps/myapp scaled

而且service自动关联到三个pod:

ilinux@master:~$ kubectl describe svc myapp
Name:              myapp
Namespace:         default
Labels:            app=myapp
Annotations:       <none>
Selector:          app=myapp
Type:              ClusterIP
IP:                10.105.212.160
Port:              80-80  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.163:80,10.244.2.166:80,10.244.2.167:80
Session Affinity:  None
Events:            <none>

实际上,curl访问时,pod会默认随机调度,并非轮询。因为它使用iptables调度。如果是ipvs还能指定调度算法。

如果把replicas=2,则缩容。因为会精确符合用户定义的需求。

在同一组pod时,如果不指定clusterIP,而是指定nodePort,还能在集群外部访问。

ilinux@master:~$ kubectl create service nodeport myapp --tcp=80:80
service/myapp created
ilinux@master:~$ kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
myapp        NodePort    10.111.65.91     <none>        80:30778/TCP   5s

访问集群任何一个宿主机的端口,即可访问到service

http://192.168.2.10:30778/hostname.html

此时,实际上通过iptables的自定义链,作为目标跳转链,实现dnat转发

API Server总结

在这里插入图片描述

  • 对kubernetes集群的所有操作,必须经过API Server ,整个k8s的hub。API server自身作为集群的gateway,可以使用kubectl,UI dashboard等客户端工具与之交互
  • 客户端提交给k8s请求的格式为json。如果提交yaml,k8s会自动转化为json,这是唯一接受的序列化方案
  • 额外也支持grpc协议:google研发的分布式rpc协议。据说比http协议性能更好,用于取代restful api的设计协议
  • Etcd:保存集群的所有状态,需要把它做成高可用,如此集群才是可用的

api-version

显示api 版本

ilinux@master:~$ kubectl api-versions
admissionregistration.k8s.io/v1
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
...

支持很多类型的资源,pod,controller,service… 如果service改变,API只有一个版本,则所有资源都需要从新打包一次,演进一次。

因此,k8s把API分类,分解到不同的群组当中。api server 把api 接口的资源分为了多个逻辑组合。其中每个组合都是相关的类型放置在一起,每个组合成称为api group。

每个组的版本,可以独立演进和迭代。而且每个组还可以多版本并存,因此每个资源必然是某个群组下的某个类型,并且可以存在多个版本如apps/v1和apps/v1beta1 。而同一种资源类型在不同版本下,可能支持的属性不同。

资源对象的配置格式

  • API server接受和返回的所有JSON对象都遵循同一个模式,它们都具有“kind”和“apiVersion”字段,用于标识对象所属的资源类型、API群组及相关的版本
  • 大多数的对象或列表类型的资源还需要具有三个嵌套型的字段:metadata、spec和status
    • metadata字段为资源提供元数据信息,例如名称、隶属的名称空间和标签等;
    • spec用于定义用户期望的状态,不同的资源类型,其状态的意义各有不同,例
      如Pod资源最为核心的功能在于运行容器;
    • status则记录着活动对象的当前状态信息,它由Kubernetes系统自行维护,对
      用户来说为只读字段;
  • “kubectl api-resources”命令可以获取集群支持使用的所有资源类型

和解循环

和解循环(Reconciliation Loop)

  • 客户端向API server提交POST请求以创建对象

    • 通过JSON格式的body提交

    • YAML格式需要事先完成向JSON的转换

    • 对象配置信息保存于etcd中,其定义出的状态也称为“期望的状态(spec)”

  • 控制器负责将其创建为Kubernetes集群上的具体对象(活动对象),并确保其当前状态(status)与用户定义的期望状态相同;

    • status由控制器自行维护,而spec则由用户进行提交
    • 活动对象在运行过程中因节点故障等原因可能会在某一时刻导致其status不再吻合于spec
    • 控制器通过和解循环(loop)不间断地监控着相关对象的当前状态,在对象的当前状态
      发生改变时运行合适的操作让其当前状态无限接近期望的状态

在这里插入图片描述

使用配置文件yaml的好处:更加精细和详细定义资源格式,而且能够复用,可借助版本控制工具git,此时还能追踪内容变动,每次版本变动发生了哪些修改。比如:本地编写yaml,push到git,然后pull到api -server,然后应用于k8s。

RESTFUL WEB Services:表征状态转移

在这里插入图片描述

它是一种架构范式,能够设计用于分布式组件相互通信和调用的方式,调用很简洁。每个被操作数据对象都被操作为如下格式:

Protocol Host(domain name) port appkication context version parameter

比如:http://localhost:9999/restfulserveices/v1/users【资源类型】/{id}【资源id】

因此,操作k8s的资源类型也能直接使用restful风格的api的方式来引用,并且put,get,delete等。当然也有更简单的命令如kubectl delete,kubectl get等。

Logo

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

更多推荐