bingmous

欢迎交流,不吝赐教~

导航

Kubernetes(k8s)学习笔记

kubernetes概述

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

传统的应用部署方式是通过插件或脚本来安装应用。这样做的缺点是应用的运行、配置、管理、所有生存周期将与当前操作系统绑定,这样做并不利于应用的升级更新/回滚等操作,当然也可以通过创建虚拟机的方式来实现某些功能,但是虚拟机非常重,并不利于可移植性。

新的方式是通过部署容器方式实现,每个容器之间互相隔离,每个容器有自己的文件系统,容器之间进程不会相互影响,能区分计算资源。相对于虚拟机,容器能快速部署,由于容器与底层设施、机器文件系统解耦的,所以它能在不同云、不同版本操作系统间进行迁移。

容器占用资源少、部署快,每个应用可以被打包成一个容器镜像,每个应用与容器间成一对一关系也使容器有更大优势,使用容器可以在build 或release 的阶段,为应用创建容器镜像,因为每个应用不需要与其余的应用堆栈组合,也不依赖于生产环境基础结构,这使得从研发到测试、生产能提供一致环境。类似地,容器比虚拟机轻量、更“透明”,这更便于监控和管理。

Kubernetes 是Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。在生产环境中部署一个应用程序时,通常要部署该应用的多个实例以便对应用请求进行负载均衡。

在Kubernetes 中,我们可以创建多个容器,每个容器里面运行一个应用实例,然后通过内置的负载均衡策略,实现对这一组应用实例的管理、发现、访问,而这些细节都不需要运维人员去进行复杂的手工配置和处理。

kubernetes的功能

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

自愈能力:

  • 容器失败时对容器进行重启
  • 当部署的节点有问题时,会对容器进行重新部署和调度
  • 当容器未通过健康检查时,不会对外提供服务,直到服务正常

水平扩展:

  • 通过简单的命令、用户UI 界面或基于CPU 等资源使用情况,对应用容器进行规模扩大或规模剪裁

服务发现:

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

滚动更新:

  • 可以根据应用的变化,对应用容器运行的应用,进行一次性或批量式更新

版本回退:

  • 可以根据应用部署情况,对应用容器运行的应用,进行历史版本即时回退

密钥和配置管理:

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

存储编排:

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

批处理:

  • 提供一次性任务,定时任务;满足批量数据处理和分析的场景

  • 应用部署架构:

    • 无中心(ClusterFS)
    • 有中心(HDFS, k8s)

kubernetes集群架构

官方文档:https://kubernetes.io/docs/concepts/architecture/
image

有两个工作角色:master node(control plane)和worker node

  • master node:是集群的控制节点,对集群进行调度管理,接收集群外用户的操作请求,由以下四个组件组成:
    • API Server:集群统一入口,以restful方式接处理请求,交给etcd进行存储
    • Scheduler:节点调度,用于选择指定node节点进行应用部署
    • Controller-manager:处理集群中常规后台任务,一个资源对应一个控制器,如deployment(kubectl api-resources
    • etcd数据库:存储系统,用于保存集群相关的数据
  • workder node:集群的工作节点,运行用户的业务应用容器
    • kubelet:node节点代表,管理本机容器,类似于一个agent
    • kube-proxy:提供网络代理,负载均衡等操作
    • docker:实际运行容器的引擎,可以是其它引擎

核心概念

  • namespace:命名空间,隔离资源,但不隔离网络
  • pod:最小部署单元,一组容器的集合,共享网络,生命周期短暂
  • controlller:确保预期pod副本数量,进行无状态有状态应用部署,确保所有的node运行同一个pod,一次性任务和定时任务
  • service:定义一组pod的访问规则

由service进行统一访问,由controller进行创建pod

资源对象:

  • Namespace
  • Pod,直接部署单个pod
  • Deployment,用于部署无状态应用
  • StatefulSet,用于部署有状态应用
  • DaemonSet,在每个节点部署守护进程
  • Job,用于部署只执行一次的任务
  • CronJob,用于部署定时执行的任务
  • Service,用于定义一组逻辑pod,通过selector进行分组
    • ClusterIP类型
    • NodePort类型
    • LoadBalance类型(用于公有云进行负载均衡)

kubernetes集群搭建

https://www.cnblogs.com/bingmous/p/15643680.html

高可用集群

实现过程:

etcd高可用:采用3 个节点组建集群实现高可用

master高可用:kube-controller-mansger 和kube-scheduler 组件自身通过选择机制已经实现了高可用,所以Master 高可用主要针对kube-apiserver 组件,而该组件是以HTTP API 提供服务,因此高可用与Web服务器类似,增加负载均衡器对其负载均衡即可,并且可水平扩容

yaml文件

k8s集群中对资源管理和资源对象编排部署都可以通过声明YAML文件进行,也就是把需要对资源对象的操作编辑到YAML文件中,我们把这种文件叫做资源清单文件,通过kubectl命令直接使用资源清单文件就可以实现对大量的资源对象进行编排部署

使用说明:https://www.cnblogs.com/bingmous/p/15643686.html

k8s的资源定义中,一般分为两个部分,一部分是控制器的定义,另一个部分是被控制对象的定义

如:

apiVersion: apps/v1		# api版本,使用kubeclt api-versions可以查看当前k8s支持的api版本
kind: Deployment	# 资源类型,使用kubectl api-resources可以查看当前k8s支持的资源类型,以及缩写,也是一个控制器
metadata:
  name: xxx-deployment	# 资源的元数据
  namespace: default	# 命名空间
spec:	# 资源规格
  replicas: 3	# 副本数
  selector:		# 标签选择器
    matchLabels:
      app: nginx
  template:		# pod模板
    metadata:	# pod的元数据
      labels:
        app: nginx
    spec:	# pod规格
      containers:	# 容器配置
        - name: nginx
          image: nginx:1.16
          ports:
            - containerPort: 80

在实际中,一般不会手写,因为里面有太多的配置,会使用生成的方式,并在上面进行修改

# 如果资源还没有部署,可以使用kubectl create生成
kubectl create deployment mynginx --image=nginx -o yaml --dry-run > mynginx.yml

# 如果资源已经部署,可以使用kubectl get导出yml描述文件
kubectl get deploy mynginx -o yaml > mynginx.yml

命令行工具kubectl

kubectl是k8s集群的命令行工具,通过kubectl 能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署,是一个客户端,控制集群管理,向apiserver发送restful请求,一般调试时使用,实际中是使用资源描述文件

命令总结:https://www.cnblogs.com/bingmous/p/17811353.html

kubernetes基本概念(namespace)

使用namespace隔离资源,并不隔离网络

kubectl create ns hello # 创建命名空间
kubectl delete ns hello # 删除命名空间

使用yaml资源描述创建:

apiVersion: v1
kind: Namespace
metadata:
  name: hello

kubernetes核心技术(Pod)

Pod概述

Pod是k8s系统中可以创建和管理的最小单元,是资源对象模型中由用户创建或部署的最小资源对象模型,也是在k8s上运行容器化应用的资源对象,其他的资源对象都是用来支撑或者扩展Pod对象功能的,比如控制器对象是用来管控Pod对象的,Service或者Ingress资源对象是用来暴露Pod引用对象的,PersistentVolume资源对象是用来为Pod提供存储等等,k8s 不会直接处理容器,而是Pod,Pod 是由一个或多个container 组成

Pod 是k8s最重要的概念,每一个Pod都有一个特殊的被称为“根容器”的Pause容器。Pause容器对应的镜像属于k8s平台的一部分,除了Pause容器,每个Pod还包含一个或多个紧密相关的用户业务容器

Pod基本概念

  • 最小部署的单元(专用ip)
  • 包含多个容器(一组容器的集合,共享网络,共享存储)
  • 一个pod中的容器共享网络命名空间
  • pod是短暂的(重启后ip可能会发送变化)

Pod存在的意义

  • 创建容器使用docker,一个docker对应一个容器,一个容器有进程,一个容器运行一个应用程序
  • Pod是多进程设计,运行多个应用程序(一个Pod有多个容器,每个容器有一个进程,对应一个应用程序)
  • Pod存在是为了亲密性应用(两个应用进行交互,网络调用,两个应用频繁调用)
# 创建pod,运行一个nginx镜像
kubectl run mynginx --image=nginx
# 查看pod
kubectl get pod
kubectl get pod -o wide # 每个pod都有一个ip,在集群内部,任意一个节点都可访问这个ip来访问pod
# 查看pod日志
kubectl logs mynginx
kubectl describe pod mynginx
# 删除pod
kubectl delete pod mynginx

使用yaml创建pod:

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: mynginx
  name: mynginx
  namespace: default
spec:
  containers:
  - image: nginx
    name: mynginx

也可以使用Deployment进行部署,它是比pod更高级的资源控制对象:
多副本控制

kubectl create deployment my-dep --image=nginx --replicas=3
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: my-dep
  name: my-dep
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-dep
  template:
    metadata:
      labels:
        app: my-dep
    spec:
      containers:
      - image: nginx
        name: nginx

扩缩容
将副本数调整为5:kubectl scale --replicas=5 deployment/my-dep,也可以直接修改kubectl edit deployment my-dep

自愈
如果一个pod在一个节点上出现了问题,会自动调度到别的节点上

滚动更新

kubectl set image deployment/my-dep nginx=nginx:1.16.1 --record # 记录本次更新的命令
kubectl rollout status deployment/my-dep
kubectl edit deployment/my-dep # 也可以直接edit

版本回退

#历史记录
kubectl rollout history deployment/my-dep

#查看某个历史详情
kubectl rollout history deployment/my-dep --revision=2

#回滚(回到上次)
kubectl rollout undo deployment/my-dep

#回滚(回到指定版本)
kubectl rollout undo deployment/my-dep --to-revision=2

Pod实现机制

pod本身就是一个逻辑的概念,容器之间原本是通过namespace和cgroups实现的隔离,如果要实现共享,就要考虑如何打破这个隔离,具体是通过网络和存储实现的。

共享网络

前提条件:网络的共享必须是在同一个namespace中

创建pod时会先创建一个Pause容器(根容器,infra容器),再把其他容器加入到Pause容器的namespace,让所有业务容器在同一个namespace中,实现网络共享(ip,mac,port)

infra容器是一个非常小的镜像,700kb左右,是一个c语言写的,永远处于暂停状态的容器,其他容器通过join namespace的方式加入到infra容器的网络namespace中。

因此在pod创建的时候,会首先创建pause容器,而这个容器的生命周期与pod的生命周期是相同的,与pod中其他的容器是无关的,这也就是在k8s中,允许单独更新pod里面的某个镜像,这个操作不会重建pod,也不会重启,这是非常重要的一个设计。

pause容器主要为其他业务容器提供一下功能:

  • 在pod中担任与其他容器namespace共享的基础
  • 启动pid命名空间,开启init进程

共享存储

引入数据卷volumn进行持久化存储,实现共享存储

在docker容器的概念中也有数据卷的概念,是指一个容器的数据可以持久化到宿主机上,容器重启后可以获取到之前存储的数据。在pod中,也可以创建数据卷,一个pod中的多个容器可以共享一个数据卷,这样就可以很容易的在一个pod的多个容器之间共享数据了

Pod拉取策略、资源限制、重启策略、健康检查

镜像拉取策略:

spec.containers[].imagePullPolicy

  • IfNotPresent,不存在时拉取,默认值
  • Always,每次创建pod都重新拉取
  • Never,pod永远不主动拉取镜像

Pod资源限制:

  • spec.containers[].resources.requests.memory,请求内存大小,分配不到则无法启动
  • spec.containers[].resources.requests.cpu,请求cpu大小,如1000m表示1核
  • spec.containers[].resources.limits.memory,pod使用最大内存大小,超过则被杀死
  • spec.containers[].resources.limits.cpu,cpu使用的最大核数,可以适当调大,因为cpu是弹性资源

Pod重启策略:

spec.restartPolicy

  • Always,容器终止退出后,总是重启容器,默认值
  • OnFailure,当容器异常退出时(错误码非0),才重启容器,一般只用于只执行一次的操作
  • Never,容器退出也不重启容器,一般批量任务时使用,只需要执行一次

Pod健康检查:

通过kubectl查看pod正在运行,但是实际可能无法提供服务了,比如java进程oom了,进程还在,但是无法提供服务了,pod支持在应用层面健康检查,pod健康检查有两种:

  • 存活检查(livenessProbe),检查失败将杀死容器,根据restartPolicy操作,spec.containers[].livenessProbe
  • 就绪检查(readinessProbe),检查失败 把Pod从service endpoints中移除,spec.containers[].readinessProbe

Probe支持三种检查方法

  • httpGet,发送http请求,返回200-400状态码则正常
  • exec,执行shell命令,返回状态码是0则成功
  • tcpSocket,发起tcp socket,建立成功则成功
spec: # pod规格
  containers:
    - name: nginx
      image: nginx:1.15
      imagePullPolicy: Always # 镜像拉取策略
      livenessProbe: # 存活探针
        exec:
          command:
            - cat
            - /tmp/healthy
        initialDelaySeconds: 5
        periodSeconds: 5
      resources: # 容器资源限制
        requests: # 容器创建时请求的大小,分配不到则无法启动
          memory: 64M
          cpu: 1000m
        limits: # 容器使用资源超过该大小容器会被杀死
          memory: 64M
          cpu: 1000m
  restartPolicy: Never

创建Pod流程

image

  • kubectl命令执行创建pod操作,向apiserver发送创建请求
  • apiserver将pod创建信息写入etcd
  • scheduler监听到有创建pod的事件,通过apiserver从etcd读取到pod信息,开始检查可以在哪个节点创建该pod,并调用apiserver将绑定后的pod信息写入etcd
  • kubelet监听到有当前节点创建pod的事件,通过apiserver从etcd读取pod信息,开始调用docker命令进行创建容器,创建完成后调用apiserver将pod状态写入etcd

mater节点 -- apiserver -- etce -- scheduler -- apiserver -- etcd
worker节点 -- kubelet -- apiserver -- etcd -- docker
都是通过apiserver读取或写入etcd

调度策略

影响pod在哪个节点上创建的因素

资源限制

资源限制:spec.containers[].resources,根据request找到足够资源的节点调度

节点选择器

节点选择器:spec.nodeSelector.my_label_key,根据nodeSelector下的标签匹配情况进行选择节点

创建标签:kubectl label node my_node my_label_key=my_value,给节点创建标签
查看标签:kubectl get nodes my_node --show-labels

节点亲和性

节点亲和性(nodeAffinity)与节点选择器类似,根据标签匹配进行调度,但比节点选择器更强大

  • 硬亲和性:约束条件必须满足,spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution
  • 软亲和性:尝试满足,不保证,spec.affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution

支持操作符:In, NotIn, Exists, Gt, Lt, DoesnotExists

如:

spec: # pod规格
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
            - key: my_label_key # 这个key对应的value必须在以下value里面才进行调度
              operator: In
              values:
                - dev
                - test
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 1
          preference:
            matchExpressions:
              - key: my_label_key2 # 这个key对应的value在以下value里面会进行优先调度
                operator: In
                values:
                  - other

污点和污点容忍

污点和污点容忍,不做普通分配调度,是节点属性,特定场景下使用,节点选择器和节点亲和性是Pod属性,调度时实现

如:专用节点、配置特定硬件的节点、基于污点进行驱逐

污点值有三个:

  • NoSchedule: 一定不被调度
  • PreferNoSchedule: 尽量不被调度
  • NoExecute: 不会调度,并且还会驱逐已有Pod
## 查看污点情况
kubectl describe node my_node | grep Taints

## 添加污点,kubectl taint node <node> key=value:污点值
kubectl taint node my_node my_label_key=my_label_value:NoSchedule

## 删除污点
kubectl taint node my_node my_label_key:Noschedule- # 注意最后有个-

污点容忍:即使是NoSchedule,添加污点容忍也可以调度到

spec:
  tolerations: # 如果节点有以下情况,也是可以容忍的,会被调度到
  - key: "my_label_key"
    operator: "Equal"
    value: "my_label_value"
    effect: "NoSchedule"

kubernetes核心技术(Controller)

controller(workload)是在集群上管理和运行容器的对象,pod通过controller实现应用的运维(伸缩,滚动升级等),controller通过label(spec.template,pod的模板)和selector(spec.selector,控制器的selector)来控制指定的pod

一个资源对应着一个controller,如deployment资源对应着一个deployment controller

无状态应用部署(deployment控制器)

deployment概述和应用场景:

  • 部署无状态应用
  • 管理Pod和ReplicaSet
  • 部署滚动升级等功能(应用场景:web服务、微服务)

使用deployment部署应用:

## 部署应用(集群内使用)
kubectl create deployment web --image=nginx # 直接部署一个应用,主要是做测试,因为命令无法复用,可以写入到yaml里,修改配置,进行复用
kubectl create deployment web --image=nginx --dry-run -o yaml > web.yaml # 生成yaml文件,里面deployment控制器的selector已经与template的标签对应了
kubectl apply -f web.yaml # 使用yaml文件部署(集群内部访问)
kubectl get pods # 查看

## 对外暴露端口(集群每个节点都可以访问这个暴露的端口)
kubectl expose depoyment web --port=80 --type=NodePort --targetPort=80 --name web1  --dry-run -o yaml > web1.yaml # 对外暴露端口,生成yaml文件
kubectl apply -f web1.yaml # 使用yaml文件对外发布(集群外部可以访问)

# 查看
kubectl get pods,svc # services的简写svc

deployment应用升级回滚和弹性伸缩

## yaml文件里版本1.14升级到1.15
kubectl set image deployment web nginx=nginx:1.15 # 会自动启动新pod使用新镜像,并删除旧pod,升级过程中服务不中断

# 查看升级状态
kubectl rollout status deployment web # 查看升级状态
kubectl rollout history deployment web # 查看升级历史

## 回滚版本
kubectl rollout undo deployment web # 回滚到上一个版本
kubectl rollout undo deployment web --to-revision=2 # 回滚到指定版本

## 弹性伸缩
kubectl scale deployment web --replicas=10

有状态应用部署(StatefulSet控制器)

无状态应用:认为Pod都一样、没有顺序要求、不考虑在哪个node运行、随意进行伸缩和扩展

有状态应用:都要考虑,让每个Pod独立,保持Pod启动顺序和唯一性

  • 使用唯一网络标识符,持久存储实现
  • 有序

使用无头service:ClusterIP的值为null,通过域名的形式来保持唯一,域名生成的规则为:StatefulSet最终生成的pod名称.headless service名称.名称空间.svc.cluster.local

有状态应用即使有存储,如果在别的节点新启动了pod,网络、数据应该都保证不变

有状态应用部署:

apiVersion: v1 # 要先定义一个headless的service
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
    - port: 80
      name: web
  clusterIP: None # headless service,定义clusterIP值为None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet # 控制器类型为StatefulSet
metadata:
  name: nginx-statefulset # 为根据这个为每个pod生成唯一pod名称,会在后面加后缀-0 -1,而不是无状态pod的随机值
  namespace: default
spec:
  serviceName: nginx
  replicas: 3 # 有状态应用 三个副本 每个pod都是独立的
  selector:
    matchLables:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.15
          ports:
            - containerPort: 80

部署:

# kind: StatefulSet
kubectl apply -f sts.yaml

# 每个Pod都有唯一的固定名称 而不是自动生成的
kubectl get pods
kubectl get svc # 查看无头service

# 唯一域名生成规则:pod唯一的固定名称.headless service名称.名称空间.svc.cluster.local

# 删除所有的无状态应用配置
kubectl delete statefullset --all

部署守护进程(DaemonSet控制器)

在每个node上运行一个pod,新加入的node也同样运行一个pod,这个pod作为这个节点的守护pod

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: my-daemonset
  labels:
    app: my-app
spec:
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: logs
          image: nginx
          ports:
            - containerPort: 80
            volumeMounts:
              - name: varlog
                mountPath: /tmp/log
       volumes:
         - name: varlog
           hostPath:
             path: /var/log

部署:

# kind: DaemonSet
kubectl apply -f ds.yaml

一次性任务

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
        - name: pi
          image: perl
          command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4 # 如果执行失败会重新尝试支持的次数,默认6

创建任务:

# kind: Job
kubectl create -f job.yaml

## 查看
kubectl get pods
kubectl get jobs

## 删除任务
kubectl delete -f job.yaml

定时任务

apiVersion: batch/v1/beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "* * * * * *"
  template:
    spec:
      containers:
        - name: hello
          image: busybox
          args: ["/bin/sh", "-c", "date;echo Hello"]
      restartPolicy: OnFailure

创建任务:

# kind: CronJob
# 创建任务
kubectl apply -f cronjob.yaml

## 查看
kubectl get pods
kubectl get cronjobs

# 查看pod标准输出
kubectl logs pod名称

kubernetes核心技术(Service)

Service概述

service存在意义:

  • 防止Pod失联(服务发现),Pod改变时ip地址也改变,通过注册pod的ip到service防止失联,访问service来访问pod
  • 定义一组Pod的访问策略(负载均衡)

Pod和service关系:与deployment相同,是通过控制器的selector和labels关联,service有一个虚拟ip(只能集群内部才能访问)

对于同一组pod,也可以定义多个service

常用Service类型

  • ClusterIP:集群内部使用
  • NodePort:对外访问使用
  • LoadBalancer:对外访问应用使用,可以连接公有云做到负载均衡

service的定义:

# 导出现有的 进行修改
kubectl get service xxx -o yaml > service.yaml

# 在创建时 不执行 输出为yaml,暴露deployment为一个service,在pod内部也可以通过域名访问,service名称.命名空间.svc
kubectl expose depoyment web --port=80 --type=NodePort --target-port=80 --name web1  --dry-run -o yaml > web1.yaml # 会生成service的定义

kubectl get pod -l app=web # 根据标签检索pod

如果类型为NodePort,有一个参数spec.externalTrafficPolicy,值为Cluster或者Local,默认前者,表示在使用NodePort访问时,是否修改当前请求中的sourceIp并进行负载均衡。如果是Local,则不修改,使用当前NodePort的请求只会转发到当前Node节点的pod上

kubernetes核心技术(配置管理)

Secret

作用:加密数据存在etcd里面,让Pod容器以Volume方式进行访问,base64加密
场景:凭证

创建加密数据:

apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  username: xxx # 使用base64进行编码后再存储
  password: xxx

创建:

# kind: Secret
kubectl create -f secret.yaml

## 查看
kubectl get secret

以变量形式挂载到Pod中:

apiVersion: v1
kind: Pod # 这里的资源类型是Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: nginx
      image: nginx
      env:
        - name: USERNAME
          valueFrom:
            secretKeyRef:
              name: my-secret # 从secret的my-secret获取
              value: username # 存储是的key为username
---
# 如果是下载镜像,使用用户名密码,也可以使用secret
apiVersion: v1
kind: Pod
metadata:
  name: private-nginx
spec:
  containers:
  - name: private-nginx
    image: mynginx:v1.0
  imagePullSecrets:
  - name: my-register-secret

以数据卷的形式挂载到Pod中

apiVersion: v1
kind: Pod # 这里的资源类型是Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: nginx
      image: nginx
      volumeMounts:
        - name: foo
          mountPath: /etc/foo # 在容器的这个目录下会有两个文件,username和password,是存储在my-secret里面的数据
          readOnly: true
  volumes:
    - name: foo
      secret:
        secretName: my-secret # 从secret的my-secret获取

ConfigMap

作用:存储不加密数据到etcd,让Pod以变量或Volume挂载到容器中
场景:可以从配置文件读取配置,存储到etcd中

pv/pvc可以用来挂载目录,如果只需要挂载文件可以使用configmap

# 创建ConfigMap 从文件中读取配置,并存储到configmap中
kubectl create configmap redis-config --from-file=redis.conf

## 查看
kubectl get cm
kubectl get cm -oyaml # 在data字段里存储数据,key默认为文件名,value为文件内容
kubectl descrbe cm redis-config # 详细查看

创建一个pod,使用configmap存储的配置文件挂载进容器:

# 这样挂载后,在容器内部/redis-master目录下会有一个配置文件redis-config,是从configmap中挂载的
# 如果修改configmap中的数据,会同步进容器
apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  containers:
  - name: redis
    image: redis
    command:
      - redis-server
      - "/redis-master/redis.conf"  # 指的是redis容器内部的位置
    ports:
    - containerPort: 6379
    volumeMounts:
    - mountPath: /data
      name: data
    - mountPath: /redis-master # 挂载的容器内的目录
      name: config # 挂载的名称
  volumes:
    - name: data
      emptyDir: {}
    - name: config # 挂载的名称
      configMap: # 对应的是configMap
        name: redis-config # 是configMap中的redis-config
        items:
        - key: redis-config # 在configmap redis-config中,挂载的数据key是redic-config
          path: redis-config # 挂载为这个文件

以数据卷的形式挂载到Pod中

apiVersion: v1
kind: Pod # 这里的资源类型是Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: nginx
      image: nginx
      volumeMounts:
        - name: foo
          mountPath: /etc/foo # 在容器的这个目录下会有redis.conf配置文件 是从configMap创建时获取的
          readOnly: true
  volumes:
    - name: foo
      configMap: # 这里从configMap获取配置进行挂载
        name: redis-config # 前面创建configMap时配置的名字

以变量形式挂载到Pod中:
先创建ConfigMap资源

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
data:
  k1: v1
apiVersion: v1
kind: Pod # 这里的资源类型是Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: nginx
      image: nginx
      env:
        - name: ABC
          valueFrom:
            configMapKeyRef:
              name: my-config # 从前面创建的configMap获取 这里的名字是configMap的名字
              value: k1 # 存储是的key为k1

kubernetes核心技术(集群安全机制)

概述

访问k8s集群时,需要经过三个步骤完成具体操作:(进行访问时都需要经过api server做统一协调,访问过程中需要证书、token或者用户名+密码;如果访问pod还需要serviceAccount)

  • 认证:
    • 传输安全:对外不暴露8080端口,只能对内使用,对外使用6443端口
    • 客户端认证常用方式:
      • https证书认证,基于ca证书
      • http token认证,通过token识别用户
      • http基本认证,用户名+密码
  • 鉴权(授权):基于RBAC进行鉴权操作(基于角色访问控制)
  • 准入控制:就是准入控制器列表,有请求内容就通过,没有就拒绝

RBAC(role based access control)

这个模型有这样几个部分:角色、主体,角色绑定

其中不同的角色可以分配不同的权限,通过角色绑定将主体绑定到特定的角色上,那么主体就有了角色可以进行的操作。

  • 角色
    role:特定命名空间访问权限。其中ClusterRole,拥有所有命名空间访问权限

  • 角色绑定
    roleBingding:角色绑定到主体,其中ClusterroleBingding将集群角色绑定到主体

  • 主体
    user:用户
    group:用户组
    serviceAccount:服务账户,一般用于pod访问

kubectl get ns # namespace
kubectl create ns roletest

RBAC实现鉴权

二进制搭建的集群测试:

# 创建命名空间进行测试
kubectl create ns roleDemo

# 在新创建的命名空间创建Pod
kubectl run nginx --image=nginx -n roleDemo
kubectl get pods -n roleDemo # 查看

创建角色 kind: Role,指定角色可以做的操作

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: roleDemo
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

创建角色:

kubectl apply -f rbac-role.yaml
kubectl get role -n roleDemo # 查看

创建角色绑定 kind: RoleBinding,将用户lucy绑定到角色pod-reader上,那么用户mary就只能做角色pod-reader指定的操作

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-pods
  namespace: roleDemo
subjects:
- kind: User
  name: mary # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role #this must be Role or ClusterRole
  name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
  apiGroup: rbac.authorization.k8s.io

创建角色绑定:kubectl apply -f rbac-rolebinding.yaml

使用证书识别身份mary:


cat > mary-csr.json <<EOF
{
  "CN": "mary",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "BeiJing",
      "ST": "BeiJing"
    }
  ]
}
EOF

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes mary-csr.json | cfssljson -bare mary

kubectl config set-cluster kubernetes \
  --certificate-authority=ca.pem \
  --embed-certs=true \
  --server=https://192.168.33.102:6443 \
  --kubeconfig=mary-kubeconfig

kubectl config set-credentials mary \
  --client-key=mary-key.pem \
  --client-certificate=mary.pem \
  --embed-certs=true \
  --kubeconfig=mary-kubeconfig

kubectl config set-context default \
  --cluster=kubernetes \
  --user=mary \
  --kubeconfig=mary-kubeconfig

kubectl config use-context default --kubeconfig=mary-kubeconfig

测试鉴权是否生效:

kubectl get pods -n roleDemo # 正常访问资源
kubectl get svc -n roleDemo # 无法访问资源

kubernetes核心技术(Ingress)

官方文档:https://kubernetes.io/docs/concepts/services-networking/ingress/ ,ingress已经停止更新了,新特性会添加到Gateway API中,https://kubernetes.io/docs/concepts/services-networking/gateway/

ingress-nginx文档地址:https://kubernetes.github.io/ingress-nginx/ ,本身就是使用nginx实现的

概述

使用Service里面的NodePort会在每个节点上暴露这个端口,每个端口只能使用一次,实际外部访问中都是使用域名,根据不同的域名跳转到不同的端口服务中,如xxx.com

Ingress是Service的统一网关入口

pod和ingress通过service关联,ingress作为统一入口(域名),由service关联一组pod,弥补NodePort的不足

使用ingress:

  • 部署ingress controller
  • 创建ingress规则

Ingress对外暴露应用

# 先创建nginx应用,对外暴露端口使用NodePort
kubectl create deployment web --image=nginx
kubectl expose deployment web --port=80 --target-port=80 --type=NodePort

# 部署ingress Controller,注意将hostNetwork改成true
kubectl apply -f ingress-controller.yaml
kubectl get pods -n ingress-nginx # 查看

# 创建规则 -- kind: Ingress
kubectl apply -f ingress-rule.yaml

# 查看service ingress-nginx会暴露两个端口分别用来访问http和https
kubectl get svc -A

# 查看ingress
kubectl get ingress

# 编辑ingress
kubectl edit ing ingress_name

ingress-controller.yaml,这里是官方维护的ingress-nginx

点击查看代码

apiVersion: v1
kind: Namespace
metadata:
  name: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-configuration
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: tcp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: udp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nginx-ingress-serviceaccount
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: nginx-ingress-clusterrole
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - endpoints
      - nodes
      - pods
      - secrets
    verbs:
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - services
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - events
    verbs:
      - create
      - patch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses/status
    verbs:
      - update

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: nginx-ingress-role
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - pods
      - secrets
      - namespaces
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - configmaps
    resourceNames:
      # Defaults to "(election-id)-(ingress-class)"
      # Here: "(ingress-controller-leader)-(nginx)"
      # This has to be adapted if you change either parameter
      # when launching the nginx-ingress-controller.
      - "ingress-controller-leader-nginx"
    verbs:
      - get
      - update
  - apiGroups:
      - ""
    resources:
      - configmaps
    verbs:
      - create
  - apiGroups:
      - ""
    resources:
      - endpoints
    verbs:
      - get

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: nginx-ingress-role-nisa-binding
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: nginx-ingress-role
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: nginx-ingress-clusterrole-nisa-binding
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: nginx-ingress-clusterrole
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
      annotations:
        prometheus.io/port: "10254"
        prometheus.io/scrape: "true"
    spec:
      hostNetwork: true
      # wait up to five minutes for the drain of connections
      terminationGracePeriodSeconds: 300
      serviceAccountName: nginx-ingress-serviceaccount
      nodeSelector:
        kubernetes.io/os: linux
      containers:
        - name: nginx-ingress-controller
          image: lizhenliang/nginx-ingress-controller:0.30.0
          args:
            - /nginx-ingress-controller
            - --configmap=$(POD_NAMESPACE)/nginx-configuration
            - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
            - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
            - --publish-service=$(POD_NAMESPACE)/ingress-nginx
            - --annotations-prefix=nginx.ingress.kubernetes.io
          securityContext:
            allowPrivilegeEscalation: true
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            # www-data -> 101
            runAsUser: 101
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
            - name: https
              containerPort: 443
              protocol: TCP
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          lifecycle:
            preStop:
              exec:
                command:
                  - /wait-shutdown

---

apiVersion: v1
kind: LimitRange
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  limits:
  - min:
      memory: 90Mi
      cpu: 100m
    type: Container


ingress-rule.yaml

点击查看代码
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: example-ingress
spec:
  rules:
  - host: a.example.com
    http:
      paths:
      - path: / # a.example.com/下的所有请求都访问web
        backend:
          serviceName: web # service的名称
          servicePort: 80  # service的端口号

ingress高级功能

只需要添加注解即可

路径重写:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#rewrite

限流:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#global-rate-limiting

kubernetes核心技术(Helm)

官网:https://helm.sh/

概述

之前部署应用需要编写yaml文件(deployment、service、ingress),如果部署的应用比较多,需要维护非常多的yaml文件,版本管理不方便

使用helm可以解决的几个问题:

  • 使用helm可以把yaml文件作为一个整体管理
  • 使用helm可以实现yaml文件高效复用
  • 使用helm可以进行应用级别的版本管理

helm是一个k8s的包管理工具,类似linux下的yum/apt,可以很方便的将之前打包好的yaml文件部署到k8s上

helm中重要概念:

  • helm:命令行客户端工具,主要用于k8s应用chart的创建、打包、发布和管理
  • chart:打包yaml,一系列用于描述k8s资源相关文件的集合
  • release:基于chart部署实体,一个chart被helm运行后会生成一个release,将在k8s中创建出真实运行的资源对象,应用级别的版本管理

架构变化:v3删除tiller,release可以在不同命名空间重用,支持将chart推送到docker仓库中

安装和配置仓库

# 安装v3版本-- 下载、解压,将helm命令移动到usr/bin目录下,或者添加系统环境变量
# 配置helm仓库
helm repo add repo1 http://mirror.azure.cn/kubernetes/charts/ # 微软仓库(推荐)
helm repo add repo2 https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts # 阿里云仓库
helm repo list # 查看仓库
helm repo update # 更新仓库地址
helm repo remove <repo_name> # 删除仓库

使用helm快速部署应用

# 使用命令搜索应用 helm search repo <chart_name>
helm search repo weave # 查找weave相关的chart

# 安装 help install <your_name> <chart_name>
helm install your_name stable/weave-scope
helm list # 查看安装后的应用
helm status your_name # 详细查看某个应用的信息

# k8s直接编辑yaml
kubectl get svc # 找到 ui-weave-scope
kubectl edit svc ui-weave-scope # 将service中的类型改为NodePort即可暴露端口

自定义chart部署

# 创建chart
helm create mychart # 会在当前目录多出来一个mychart目录

## 目录说明
# charts 空目录
# Chart.yaml 当前chart的属性配置信息
# templates chart是yaml文件集合,就放在这个目录
# values.yaml 用于定义yaml文件可以使用的全局变量

# 测试自定义chart
kubectl create deployment web --image=nginx --dry-run -o > deployment.yaml # 生成yaml
kubectl create deployment web --image=nginx # 先实际运行一下
kubectl expose deployment web --port=80 --target-port=80 --dry-run -o yaml > service.yaml # 生成yaml
kubectl delete deployment web # 清除

# 把deployment.yaml和service.yaml放在templates里面

# 使用helm进行安装chart help install <your_name> <your_chart>
helm install web mychart # helm就会使用mychart里面的yaml进行安装部署了

## 应用升级
helm upgrade web mychart

chart模板使用

实现yaml高效复用:通过传递参数,动态渲染模板,yaml内容通过传入参数生成

# values.yaml定义变量和值,在template中的文件中调用
# 调用方法:{{ .Values.VarName }}, {{ .Release.Name }} # .Release获取到的是当前部署的名称 helm install web mychart中的web

# 尝试运行查看生成的文件
helm install --dry-run web2 mychart

# 通过helm部署应用
helm install web2 mychart

kubernetes核心技术(持久化存储)

k8s支持很多文件系统

nfs

nfs:网络存储,数据存储到分布式文件系统中,实际使用中需要配置nfs的地址,不安全

## 通过一台服务器做nfs服务端
yum install -y nfs-utils # k8s集群节点也要安装
vi /etc/exports
/data/nfs *{rw.no_root_squash} # 添加挂载目录,必须存在

## nfs服务端启动nfs服务
systemctl start nfs

创建pod使用nfs:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dep1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: wwwroot
          mountPath: /usr/share/nginx/html # 容器内的路径
        ports:
        - containerPort: 80
      volumes:
        - name: wwwroot
          nfs:
            server: 192.168.44.134 # nfs的服务器
            path: /data/nfs

创建pod,使用nfs

## 在k8s集群部署应用使用nfs
kubectl apply -f nfs-nginx.yaml
kubectl exec -it Name bash # 进入设置的挂载目录,可以查看到服务端挂载目录的内容

如果是多个节点都配置nfs,其中一个作为server节点,配置如下:

# 所有节点安装nfs
yum install -y nfs-utils
# 主节点配置
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
# 创建好目录
mkdir -p /nfs/data
# 启动并开机自启动 rpc绑定、nfs server
systemctl enable rpcbind --now
systemctl enable nfs-server --now
# 使配置生效
exportfs -r
# 从节点 检查可以挂载的路径
showmount -e nfs_server_ip
# 挂载nfs服务器上的目录到本机路径
mkdir -p /nfs/data
mount -t nfs nfs_server_ip:/nfs/data /nfs/data
# 测试 在server节点或挂载节点的/nfs/data目录下写入文件 都会在多个节点之间同步

存在的问题:

  • nfs上挂载的目录需要手动创建
  • pod删除时,挂载目录里的数据是不会删除的
  • 每个pod使用nfs是没有限制的

pv和pvc

pv: 持久化存储,对存储资源进行抽象,对外提供可以调用的地方(生产者)
pvc: 用于调用,不需要关心内部实现细节(消费者)

实现流程:应用部署,通过pvc绑定pv,然后就可以访问pv定义的挂载目录了,而pv定义数据存储服务器的ip、路径、存储容量、模式等信息,这样应用就可以不直接使用nfs了

如何实现动态供应?

如果要实现挂载配置文件,可以使用configmap

# 定义pv
apiVersion: v1
kind: PersistentVolume # 定义持久化存储卷,相当于集群的一种存储资源,每个pod可以取用
metadata:
  name: my-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteMany
  storageClassName: nfs
  nfs:
    path: /data/nfs
    server: 192.168.44.134

---
# 定义pvc
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: my-pvc # 这个pvc就会从pv里面绑定一个合适的,pv是静态供应,也可以动态供应,pvc需要多少pv就提供多少
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 200Mi # 定义pvc,声明需要获取的存储资源情况
  storageClassName: nfs

---
# 定义deployment 使用pvc
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dep1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: wwwroot
          mountPath: /usr/share/nginx/html
        ports:
        - containerPort: 80
      volumes:
      - name: wwwroot
        persistentVolumeClaim:
          claimName: my-pvc # 指定使用哪个pvc的资源声明

应用并查看:

kubectl apply -f xxx.yaml
# 查看pv pvc
kubectl get pv,pvc

kubernetes集群资源监控

dashboard

github:https://github.com/kubernetes/dashboard

helm安装、或者kubectl安装

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml

# 将ClusterIP改为NodePort,可以集群外访问
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard

创建访问账号:kubectl apply -f dash.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard

获取访问令牌:

kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"

获取访问外部端口,访问:https://集群任意IP:端口

kubectl get svc -A | grep kubernetes-dashboard

监控指标

集群监控:节点资源利用率、节点数、运行Pods
Pod监控:容器指标、应用程序指标

监控平台搭建方案

  • prometheus:抓取数据
    • 开源
    • 监控、报警、数据库
    • 以http协议周期性抓取监控组件状态
    • 不需要复杂的集成过程,使用http接口接入就可以了
  • Grafana:展示
    • 开源的数据分析和可视化工具
    • 支持多种数据源
# 部署prometheus
kubectl create -f node-exporter.yaml # 部署守护进程
kubectl create -f rbac-setup.yaml # 部署其他yaml文件
kubectl create -f configmap.yaml
kubectl create -f prometheus.deploy.yaml
kubectl create -f prometheus.svc.yaml

# 部署grafana
kubectl create -f grafana-deploy.yaml
kubectl create -f grafana-svc.yaml
kubectl create -f grafana-ing.yaml

# 打开grafana,用户名admin/admin,配置数据源,导入显示模板315,设置显示模板

项目部署

容器交付流程

  • 开发代码阶段(编写代码、测试、编写Dockerfile)
  • 持续交付/集成(代码编译打包、制作镜像、上传镜像仓库)
  • 应用部署(环境准备、Pod、Service、Ingress)
  • 运维(监控、故障排查、升级优化)

部署java项目

# 把java项目进行打包
# 制作镜像,可以参考spring-kubenetes官方的打包规范
docker build -t xxx:latest .
docker images # 查看
docker run -d -p 8111:8111 xxx:latest -t # 本地启动测试
# 推送镜像(阿里云)-- 参考docker学习笔记
# 部署镜像,暴露应用端口
kubectl create deployment xxx --image=镜像地址
kubectl expose deployment xxx --port=8111 --target-port=8111 --type=NodePort

总结

概念:

  • pod
  • service,逻辑上的一组pod,pod的上层网络
  • ingress,service的统一入口,service的上层网络

web:dashboard


工作负载:

  • pod,最小运行单元
  • Deployment,部署无状态应用,它有自愈、故障转移、滚动升级等功能
  • StatefulSet,部署有状态应用

服务:

  • ingress
  • service

配置和存储:

  • pv、pvc,用于挂载目录
  • configmap,挂载配置文件
  • secret,存储密码,base64加密而已

posted on 2021-06-25 11:06  Bingmous  阅读(65)  评论(0编辑  收藏  举报