K8S介绍

K8S架构

  • master:

    APISERVER:所有服务访问统一入口,负责处理接受请求的工作
    ​
    ControllerManager:控制器管理器,维持副本期望数目
    ​
    Scheduler:调度器,负责接收任务,选择合适的节点进行分配任务
    ​
    ETCD:键值对数据库,储存K8S集群所有重要信息(持久化)
  • node:

    Kubelet:直接跟容器引擎交互实现容器的生命周期管理
    ​
    Kube-proxy:负责写入规则至IPTABLES,IPVS实现服务映射访问的;负责为Service提供cluster内部的服务发现和负载均衡
    ​
    Container:容器进行时
  • 其他插件:

    COREDNS:可以为集群中的SVC创建一个域名IP的对应关系解析
    ​
    DASHBOARD:给K8S集群提供一个B/S结构访问体系

查看当前k8s支持的API版本

kubectl api-versions

POD

容器组(Pod)是Kubernetes创建或部署的最小单位 。Pod是一组容器(可包含一个或多个应用程序容器),以及共享存储(卷 Volumes)、IP 地址和有关如何运行容器的信息。

网络通讯方式

  • Pod内部通信

    同一个Pod共享同一个网络命令空间,共享同一个Linux协议栈。

    Pod内部容器之间直接通过localhost**:**端口号的方式进行通信 ,但是它们不能在同一端口上同时开启服务,否则会有端口冲突,这就是共享网络栈的意思 。
    ​
    Pod中还有一个比较特殊的叫pause的容器,这个容器运行的唯一目的是为Pod建立共享的veth0网络接口 ,其他容器共用pause的网络栈,共用存储卷。
    ​
    **总结**:即pod内部容器是通过共享一个虚拟网卡相互通信的,可以直接通过localhost相互访问,而这个虚拟网卡是通过一个特殊的容器pause创建的。 

  • 相同节点的Pod通信

​docker0是一个虚拟网桥,可以简单理解为一个虚拟交换机,它是支持该节点上的Pod之间进行IP寻址和互通的设备。Pod的IP是由docker0网桥分配的,例如上图docker0网桥的IP是172.17.0.1,它给第一个Pod分配IP为172.17.0.2。如果该节点上再启一个Pod2,那么相应的分配IP为172.17.0.3,如果再启动Pod可依次类推。因为这些Pods都连在同一个网桥上,在同一个网段内,它们可以进行IP寻址和互通

总结: Pod1与Pod2在同一个机器,由docker0的网桥直接转发请求至Pod2,不需要经过Flannel

  • 不同节点的Pod通信

Pod1与Pod2不在同一个主机,Pod的地址是与docker0在同一个网段的,但docker0网段与宿主机网卡是两个完全不同的IP网段,并且不同Node之前的通信只能通过宿主机的物理网卡进行。经Pod的IP和所在Node的IP关联起来,通过这个关联让Pod可以相互访问。需要经过Flannel

​ Pod至Service的网络:目前基于性能考虑,全部为LVS维护和转发

  • Pod到外网

​ Pod向外网发送请求,查找路由表,转发数据包到宿主机的网卡,宿主网卡完成路由选择后,iptables执行Masquerade,把源IP更改为宿主网卡的IP,然后向外网发送请求

Pod的生命周期

  • 启动pause容器

负责网络和数据卷初始化,并共享给里面的所有容器使用。

  • 启动init容器

负责pod的初始化容器,执行完后退出。正常退出完后,才能开始启动main容器

  • 启动主容器

  • 启动就绪探针

探针是由kubelet对容器执行的定期诊断

Readiness Probe同样是周期性的检测Pod,然后根据响应来判断Pod是否就绪

  1. Exec:Probe执行容器中的命令并检查命令退出的状态码,如果状态码为0则说明已经就绪。

  2. HTTP GET:往容器的IP:Port发送HTTP GET请求,如果Probe收到2xx或3xx,说明已经就绪。

  3. TCP Socket:尝试与容器建立TCP连接,如果能建立连接说明已经就绪。

Readiness Probe的工作原理

通过Endpoints就可以实现Readiness Probe的效果,当Pod还未就绪时,将Pod的IP:Port从Endpoints中删除,Pod就绪后再加入到Endpoints中

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:alpine
        name: container-0
        resources:
          limits:
            cpu: 100m
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        readinessProbe:      # Readiness Probe
          exec:              # 定义 ls /ready 命令
            command:
            - ls
            - /ready
        readinessProbe:           # readinessProbe
          httpGet:                # HTTP GET定义
            path: /read
            port: 80
        readinessProbe:             # readinessProbe
          tcpSocket:                # TCP Socket定义
            port: 80
          initialDelaySeconds:1     # 延迟1S查询
          periodSeconds:3           # 查询3S一次
          timeoutSeconds:10         # 超时时间
      imagePullSecrets:
      - name: default-secret

  • 启动存活探针

指示容器是否正在运行。如果存活探针失败,则kubelet会杀死容器,并且容器将受到重启策略的影响。

  • 启动,停止动作

容器启动前动作,和停止后动作

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:alpine
        name: container-0
        resources:
          limits:
            cpu: 100m
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        lifecycle:
          postStart:
            exec:
              command:["/bin/sh","-c","echo xxxx >> xx.txt"]
          prestop:
            exec:
              command:["/bin/sh","-c","echo xxxx >> xx.txt"]

Pod的编排与调度(控制器完成)

  • 无状态负载(Deployment)

    Kubernetes提供了Controller(控制器)来管理Pod,Controller可以创建和管理多个Pod,提供副本管理、滚动升级和自愈能力,其中最为常用的就是Deployment 。

apiVersion: apps/v1      # 注意这里与Pod的区别,Deployment是apps/v1而不是v1
kind: Deployment         # 资源类型为Deployment
metadata:
  name: nginx            # Deployment的名称
spec:
  replicas: 2            # Pod的数量,Deployment会确保一直有2个Pod运行         
  selector:              # Label Selector
    matchLabels:
      app: nginx
  template:              # Pod的定义,用于创建Pod,也称为Pod template
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:latest
        name: container-0
        resources:
          limits:
            cpu: 100m
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
      imagePullSecrets:
      - name: default-secret
扩容:
kubectl scale deployment xxxx --replicas=10
  • 有状态负载(StatefulSet)

        每个Pod都有自己单独的状态,或者存储。

        可以看看有状态负载(StatefulSet)_云容器引擎 CCE_Kubernetes基础知识_Pod的编排与调度_华为云

  • 普通任务(Job)和定时任务(CronJob)

    Job和CronJob是负责批量处理短暂的一次性任务

    Job:是Kubernetes用来控制批处理型任务的资源对象。Job管理的Pod根据用户的设置把任务成功完成就自动退出(Pod自动删除)。

    CronJob:是基于时间的Job,就类似于Linux系统的crontab文件中的一行,在指定的时间周期运行指定的Job。

Job类型说明使用示例
一次性Job创建一个Pod直至其成功结束数据库迁移
固定结束次数的Job依次创建一个Pod运行直至completions个成功结束处理工作队列的Pod
固定结束次数的并行Job依次创建多个Pod运行直至completions个成功结束多个Pod同时处理工作队列
并行Job创建一个或多个Pod直至有一个成功结束多个Pod同时处理工作队列

创建Job

apiVersion: batch/v1    # API版本 包含批处理、任务处理对象
kind: Job
metadata:
  name: pi-with-timeout
spec:
  completions: 50            # 运行的次数,即Job结束需要成功运行的Pod个数
  parallelism: 5             # 并行运行Pod的数量,默认为1
  backoffLimit: 5            # 表示失败Pod的重试最大次数,超过这个次数不会继续重试。
  activeDeadlineSeconds: 10  # 表示Pod超期时间,一旦达到这个时间,Job及其所有的Pod都会停止。
  template:                  # Pod定义
    spec: 
      containers:
      - name: pi
        image: perl
        command:
        - perl
        - "-Mbignum=bpi"
        - "-wle"
        - print bpi(2000)
      restartPolicy: Never

创建CronJob

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: cronjob-example
spec:
  schedule: "0,15,30,45 * * * *"           # 定时相关配置
  jobTemplate:                             # Job的定义
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: main
            image: pi
  • 守护进程集(DaemonSet)

       DaemonSet 确保全部(或者一些)Node上运行一个Pod的副本。当有node加入集群时,也会为他们新增一个Pod。当有Node移除,Pod也会被回收。删除DaemonSet 将会删除它创建的所有Pod。

使用DaemonSet的一些典型用法:

在每个Node上运行日志收集daemon,例如fluenth。

在每个Node上运行监控daemon,例如Prometheus

       创建DaemonSet

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx-daemonset
  labels:
    app: nginx-daemonset
spec:
  selector:
    matchLabels:
      app: nginx-daemonset
  template:
    metadata:
      labels:
        app: nginx-daemonset
    spec:
      nodeSelector:                 # 节点选择,当节点拥有daemon=need时才在节点上创建Pod
        daemon: need
      containers:
      - name: nginx-daemonset
        image: nginx:alpine
        resources:
          limits:
            cpu: 250m
            memory: 512Mi
          requests:
            cpu: 250m
            memory: 512Mi
      imagePullSecrets:
      - name: default-secret

打标签

kubectl label node xx.xx.xx.xx daemon=need

修改标签

kubectl label node xx.xx.xx.xx daemon=no --overwrite

  • 亲和与反亲和调度

Service服务

原理说明

  • apiserver用户通过kubeclt命令向apiserver发送创建service的命令,apiserver接收到请求后将数据存储到etcd中

  • 每个节点上都有一个叫做kube-proxy的进程,这个进程通过etcd中数据负责感知service,pod的变化,并将变化的信息写入本地的ipvs规则中

  • ipvs使用NAT等技术将虚拟ip的流量转至endpoint中

解决直接访问Pod的问题

apiVersion: v1
kind: Service
metadata:
  name: nginx        # Service的名称
spec:
  selector:          # Label Selector,选择包含app=nginx标签的Pod
    app: nginx
  ports:
  - name: service0
    targetPort: 80   # Pod的端口
    port: 8080       # Service对外暴露的端口
    protocol: TCP    # 转发协议类型,支持TCP和UDP
  type: ClusterIP    # Service的类型
 

说明:创建一个名为“nginx”的Service,通过selector选择到标签“app:nginx”的Pod,目标Pod的端口为80,Service对外暴露的端口为8080。

访问服务只需要通过“服务名称:对外暴露的端口”接口,对应本例即“nginx:8080”。这样,在其他Pod中,只需要通过“nginx:8080”就可以访问到“nginx”关联的Pod。

Service是如何做到服务发现的

$ kubectl describe svc nginx
Name:              nginx
......
Endpoints:         172.16.2.132:80,172.16.3.6:80,172.16.3.7:80
......
​

可以看到一个Endpoints,Endpoints同样也是Kubernetes的一种资源对象,可以查询得到。Kubernetes正是通过Endpoints监控到Pod的IP,从而让Service能够发现Pod。

$ kubectl get endpoints
NAME         ENDPOINTS                                     AGE
nginx        172.16.2.132:80,172.16.3.6:80,172.16.3.7:80   5h48m
$ kubectl get po -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP             NODE         
nginx-869759589d-dnknn   1/1     Running   0          5h40m   172.16.3.7     192.168.0.212
nginx-869759589d-fcxhh   1/1     Running   0          5h40m   172.16.3.6     192.168.0.212
nginx-869759589d-r69kh   1/1     Running   0          5h40m   172.16.2.132   192.168.0.94
 

Service的类型

Service的类型除了ClusterIP还有NodePort、LoadBalancer和Headless Service

  • ClusterIP:用于在集群内部互相访问的场景,通过ClusterIP访问Service

  • NodePort:用于从集群外部访问的场景,通过节点上的端口访问Service

  • LoadBalancer:用于从集群外部访问的场景,其实是NodePort的扩展,通过一个特定的LoadBalancer访问Service,这个LoadBalancer将请求转发到节点的NodePort,而外部只需要访问LoadBalancer

  • Headless Service:用于Pod间的互相发现,该类型的Service并不会分配单独的ClusterIP, 而且集群也不会为它们进行负载均衡和路由

yaml常用字段说明

参数名字段类型说明
apiversionstring指K8S API的版本,可以用kubectl api-version命令查询
kindstring资源类型,如pod
metadataobject元数据对象,固定值就写metadata
metadata.namestring元数据对象的名字,比如命名Pod的名字
metadata.namespacestring元数据对象的命名空间
Specobject详细定义对象,固定值就写Spec
Spec.containers[]listSpec对象的容器列表定义,是个列表
Spec.containers[].namestring定义容器的名字
Spec.containers[].imagestring定义容器的镜像

常见错误

address already in use:

level=warning msg="Error starting load balancer: listen tcp 127.0.0.1:6444: bind: address already in use"

原因:

agent服务器同时启动了K3S-master服务,导致agent一直挂载不上master。

解决方案:

netstat -tulnp | grep LISTEN #查看监控端口
journalctl -xeu k3s-agent.service #查看服务日志
service k3s stop #关闭K3S-master服务

kubectl logs 查询日志报错:

 proxyconnect tcp: proxy error from 127.0.0.1:6443 while dialing proxy.xxx.com:8080, code 503: 503 Service Unavailable

原因:

k3s配置代理,没有把自身配置到no_proxy中。

解决方案:

vim /etc/systemd/system/k3s.service.env
NO_PROXY=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16

K3S配置代理:

如果你运行 K3s 的环境中只通过 HTTP 代理进行外部连接,你可以在 K3s 的 systemd 服务上配置代理。K3s 将使用这些代理设置,并向下传递到嵌入式 containerd 和 kubelet。

K3s 安装脚本会自动使用当前 shell 中的 HTTP_PROXYHTTPS_PROXYNO_PROXY,以及 CONTAINERD_HTTP_PROXYCONTAINERD_HTTPS_PROXYCONTAINERD_NO_PROXY 变量(如果存在),并将它们写入 systemd 服务的环境文件,通常是:

  • /etc/systemd/system/k3s.service.env

  • /etc/systemd/system/k3s-agent.service.env

你也可以通过编辑这些文件来配置代理。

K3s 会自动将集群内部 Pod 和 Service IP 范围以及集群 DNS 域添加到 NO_PROXY 条目列表中。你需要确保 Kubernetes 节点本身使用的 IP 地址范围(即节点的公共和私有 IP)包含在 NO_PROXY 列表中,或者可以通过代理访问节点。

HTTP_PROXY=http://your-proxy.example.com:8888
HTTPS_PROXY=http://your-proxy.example.com:8888
NO_PROXY=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16

如果你想在不影响 K3s 和 Kubelet 的情况下为 containerd 配置代理,你可以在变量前加上 CONTAINERD_

CONTAINERD_HTTP_PROXY=http://your-proxy.example.com:8888
CONTAINERD_HTTPS_PROXY=http://your-proxy.example.com:8888
CONTAINERD_NO_PROXY=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16

K3S-agent下载镜像失败:

 rpc error: code = DeadlineExceeded desc = failed to pull and unpack image

原因:

k3s-agent上没有配置代理,或者没有配置加速器。注意一定要master配置好后再启动agent

解决方案:

vim /var/log/syslog #查看系统日志
vim /etc/systemd/system/k3s-agent.service.env  #配置agent上代理
#NO_PROXY="10.169.0.0/24,10.169.0.0/16"
#HTTP_PROXY="http://******@proxy.xxx.com:8080"
#HTTPS_PROXY="http://******@proxy.xxx.com:8080"
CONTAINERD_HTTP_PROXY=http://******@proxy.xxx.com:8080
CONTAINERD_HTTPS_PROXY=http://******@proxy.xxx.com:8080
CONTAINERD_NO_PROXY=10.0.0.0/24,100.0.0.0/24,10.169.0.0/16,10.169.0.0/24,172.19.90.131/24

vim /var/lib/rancher/k3s/agent/etc/containerd/config.toml  #配置agent加速器
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
​
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
  endpoint = ["https://fogjl973.mirror.aliyuncs.com", "https://registry-1.docker.io"]
  
  
cat >> /etc/rancher/k3s/registries.yaml <<EOF  #配置master加速器
mirrors:
  "docker.io":
    endpoint:
      - "https://fogjl973.mirror.aliyuncs.com"
      - "https://registry-1.docker.io"
EOF
​
systemctl restart k3s
service k3s-agent restart
systemctl restart containerd.service

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值